Fix T49187: inconsistent Normal Map node output for backfacing polygons.
authorAlexander Gavrilov <angavrilov@gmail.com>
Tue, 30 Aug 2016 09:48:59 +0000 (12:48 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Tue, 30 Aug 2016 09:48:59 +0000 (12:48 +0300)
There basically are two issues here: in smooth mode (and all non-tangent
normal map types) it doesn't invert the normal for backfacing polys;
on the other hand for flat shaded tangent type it is inverted too soon.

This fix does a brute force correction by checking the backfacing flag.

Reviewers: #cycles, brecht

Reviewed By: #cycles, brecht

Differential Revision: https://developer.blender.org/D2181

intern/cycles/kernel/shaders/node_normal_map.osl
intern/cycles/kernel/svm/svm_tex_coord.h

index f95e9fcfe3cecf13d1834a233e9e23b0117c3412..41bcac4fb10132705914cb6061e93f87a2c7ac0d 100644 (file)
@@ -26,6 +26,7 @@ shader node_normal_map(
        output normal Normal = NormalIn)
 {
        color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
+       int is_backfacing = backfacing();
 
        if (space == "tangent") {
                vector tangent;
@@ -34,9 +35,15 @@ shader node_normal_map(
                float is_smooth;
 
                getattribute("geom:is_smooth", is_smooth);
-               if (!is_smooth)
+               if (!is_smooth) {
                        ninterp = normalize(transform("world", "object", Ng));
 
+                       /* the normal is already inverted, which is too soon for the math here */
+                       if (is_backfacing) {
+                               ninterp = -ninterp;
+                       }
+               }
+
                // get _unnormalized_ interpolated normal and tangent
                if (getattribute(attr_name, tangent) &&
                    getattribute(attr_sign_name, tangent_sign) &&
@@ -73,7 +80,12 @@ shader node_normal_map(
        
                Normal = normalize(vector(mcolor));
        }
-       
+
+       /* invert normal for backfacing polygons */
+       if (is_backfacing) {
+               Normal = -Normal;
+       }
+
        if (Strength != 1.0)
                Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
 }
index 01dede3fff562157f54f06708cbbb6204a67d5a2..6ea2539c5438effeadcccc131d699a08215213ad 100644 (file)
@@ -277,6 +277,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
        float3 color = stack_load_float3(stack, color_offset);
        color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
 
+       bool is_backfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) != 0;
        float3 N;
 
        if(space == NODE_NORMAL_MAP_TANGENT) {
@@ -306,6 +307,12 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
                }
                else {
                        normal = ccl_fetch(sd, Ng);
+
+                       /* the normal is already inverted, which is too soon for the math here */
+                       if(is_backfacing) {
+                               normal = -normal;
+                       }
+
                        object_inverse_normal_transform(kg, sd, &normal);
                }
 
@@ -332,6 +339,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
                        N = safe_normalize(N);
        }
 
+       /* invert normal for backfacing polygons */
+       if(is_backfacing) {
+               N = -N;
+       }
+
        float strength = stack_load_float(stack, strength_offset);
 
        if(strength != 1.0f) {