Cycles: Make sphere and tube image mapping friendly with OpenCL

OpenCL doesn't let you to get address of vector components, which
is kinda annoying. On the other hand, maybe now compiler will have
more chances to optimize something out.
This commit is contained in:
Sergey Sharybin 2015-02-19 12:52:48 +05:00
parent 5004b58262
commit 3e534833e3
3 changed files with 27 additions and 22 deletions

@ -106,7 +106,9 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float
int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num];
float3 orco =
get_float3(userdata->mesh.vertices[vert_idx].undeformed_co());
map_to_sphere(&uv[0], &uv[1], orco[0], orco[1], orco[2]);
float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2]));
uv[0] = tmp.x;
uv[1] = tmp.y;
}
}

@ -368,16 +368,20 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
float3 co = stack_load_float3(stack, co_offset);
float2 tex_co;
uint use_alpha = stack_valid(alpha_offset);
if(node.w == NODE_IMAGE_PROJ_SPHERE) {
co = texco_remap_square(co);
map_to_sphere(&co.x, &co.y, co.x, co.y, co.z);
tex_co = map_to_sphere(co);
}
else if(node.w == NODE_IMAGE_PROJ_TUBE) {
co = texco_remap_square(co);
map_to_tube(&co.x, &co.y, co.x, co.y, co.z);
tex_co = map_to_tube(co);
}
float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha);
else {
tex_co = make_float2(co.x, co.y);
}
float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, srgb, use_alpha);
if(stack_valid(out_offset))
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));

@ -1457,38 +1457,37 @@ ccl_device bool ray_quad_intersect(
}
/* projections */
ccl_device void map_to_tube(float *r_u, float *r_v,
const float x, const float y, const float z)
ccl_device_inline float2 map_to_tube(const float3 co)
{
float len;
*r_v = (z + 1.0f) * 0.5f;
len = sqrtf(x * x + y * y);
float len, u, v;
len = sqrtf(co.x * co.x + co.y * co.y);
if (len > 0.0f) {
*r_u = (1.0f - (atan2f(x / len, y / len) / M_PI_F)) * 0.5f;
u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f;
v = (co.x + 1.0f) * 0.5f;
}
else {
*r_v = *r_u = 0.0f; /* To avoid un-initialized variables. */
u = v = 0.0f;
}
return make_float2(u, v);
}
ccl_device bool map_to_sphere(float *r_u, float *r_v,
const float x, const float y, const float z)
ccl_device_inline float2 map_to_sphere(const float3 co)
{
float len = sqrtf(x * x + y * y + z * z);
if(len > 0.0f) {
if(UNLIKELY(x == 0.0f && y == 0.0f)) {
*r_u = 0.0f; /* othwise domain error */
float l = len(co);
float u, v;
if(l > 0.0f) {
if(UNLIKELY(co.x == 0.0f && co.y == 0.0f)) {
u = 0.0f; /* othwise domain error */
}
else {
*r_u = (1.0f - atan2f(x, y) / M_PI_F) / 2.0f;
u = (1.0f - atan2f(co.x, co.y) / M_PI_F) / 2.0f;
}
*r_v = 1.0f - safe_acosf(z / len) / M_PI_F;
return true;
v = 1.0f - safe_acosf(co.z / l) / M_PI_F;
}
else {
*r_v = *r_u = 0.0f; /* to avoid un-initialized variables */
return false;
u = v = 0.0f;
}
return make_float2(u, v);
}
ccl_device_inline int util_max_axis(float3 vec)