From 9fcaac5009b567edc59c4831b6a0580211d1d290 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 23 Jul 2014 12:54:49 +0600 Subject: Fix T41147: Static BVH shading problem Fix T41079: Solid black render of object with negative scale and smooth shading In both cases the issue was caused by negative scaled objects with single mesh users for which scale gets applied when using static BVH. Since the on-fly normals calculation land normals for such cases weren't flipped leading them to point to a wrong direction. Added a special object flag for this, which is a bit of a bummer because now we've got less bits for real useful things, but this is the only way to get proper normals without adding more complexity in the on-fly calculations. --- intern/cycles/kernel/geom/geom_triangle.h | 9 ++++++--- intern/cycles/kernel/kernel_shader.h | 4 ++-- intern/cycles/kernel/kernel_types.h | 3 ++- intern/cycles/render/object.cpp | 2 ++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index f2f35c2efd0..f4e53be5429 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -117,17 +117,20 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderDat } /* normal on triangle */ -ccl_device_inline float3 triangle_normal(KernelGlobals *kg, int prim) +ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd) { /* load triangle vertices */ - float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim)); + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); /* return normal */ - return normalize(cross(v1 - v0, v2 - v0)); + if(sd->flag & SD_NEGATIVE_SCALE_APPLIED) + return normalize(cross(v2 - v0, v1 - v0)); + else + return normalize(cross(v1 - v0, v2 - v0)); } /* point and normal on triangle */ diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 842b9f68840..3b95d7055ac 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -86,7 +86,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, #endif if(sd->type & PRIMITIVE_TRIANGLE) { /* static triangle */ - float3 Ng = triangle_normal(kg, sd->prim); + float3 Ng = triangle_normal(kg, sd); sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); /* vectors */ @@ -165,7 +165,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat /* fetch triangle data */ if(sd->type == PRIMITIVE_TRIANGLE) { - float3 Ng = triangle_normal(kg, sd->prim); + float3 Ng = triangle_normal(kg, sd); sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); /* static triangle */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index c35aebe40f7..cfd72e1476b 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -592,7 +592,8 @@ enum ShaderDataFlag { /* object flags */ SD_HOLDOUT_MASK = 524288, /* holdout for camera rays */ SD_OBJECT_MOTION = 1048576, /* has object motion blur */ - SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */ + SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */ + SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */ SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED) }; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 027bfd71931..1f148d34ea6 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -449,6 +449,8 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u } object_flag[i] |= SD_TRANSFORM_APPLIED; + if(object->mesh->transform_negative_scaled) + object_flag[i] |= SD_NEGATIVE_SCALE_APPLIED; } else have_instancing = true; -- cgit v1.2.3