diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-15 20:35:05 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-15 20:35:05 +0400 |
commit | 6adfd91657e07e5b749fb3a7aaeeeec88fb15d04 (patch) | |
tree | 32232a0280a212d0438cb3219079a61e89632a16 /intern/cycles/kernel | |
parent | 51f36ac80ab3dbb9a34cacdcb0eda5371793b16f (diff) |
Fix #33830: cycles normal mapping was not quite correct, was not correctly
respecting the assumption that normal and tangent are interpolated without
normalization.
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/shaders/node_normal_map.osl | 20 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_tex_coord.h | 17 |
2 files changed, 24 insertions, 13 deletions
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl index dc25eb8539f..21382fab06f 100644 --- a/intern/cycles/kernel/shaders/node_normal_map.osl +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -31,15 +31,23 @@ shader node_normal_map( if (space == "Tangent") { vector tangent; + vector ninterp; float tangent_sign; - getattribute(attr_name, tangent); - getattribute(attr_sign_name, tangent_sign); + // get _unnormalized_ interpolated normal and tangent + if(!getattribute(attr_name, tangent) || + !getattribute(attr_sign_name, tangent_sign) || + !getattribute("geom:N", ninterp)) { + Normal = normal(0, 0, 0); + } + else { + // apply normal map + vector B = tangent_sign * cross(ninterp, tangent); + Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp); - tangent = transform("object", "world", tangent); - - vector B = tangent_sign * cross(NormalIn, tangent); - Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn); + // transform to world space + Normal = normalize(transform("object", "world", Normal)); + } } else if (space == "Object") Normal = normalize(transform("object", "world", vector(mcolor))); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 7a1af43b625..d793169261d 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -248,24 +248,27 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac } /* first try to get tangent attribute */ - AttributeElement attr_elem, attr_sign_elem; + AttributeElement attr_elem, attr_sign_elem, attr_normal_elem; int attr_offset = find_attribute(kg, sd, node.z, &attr_elem); int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem); + int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem); - if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) { + if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) { stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); return; } - /* ensure orthogonal and normalized (interpolation breaks it) */ + /* get _unnormalized_ interpolated normal and tangent */ float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL); float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL); + float3 normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL); - object_normal_transform(kg, sd, &tangent); - tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; + /* apply normal map */ + float3 B = sign * cross(normal, tangent); + N = normalize(color.x * tangent + color.y * B + color.z * normal); - float3 B = sign * cross(sd->N, tangent); - N = normalize(color.x * tangent + color.y * B + color.z * sd->N); + /* transform to world space */ + object_normal_transform(kg, sd, &N); } else { /* object, world space */ |