Fix #109679: Normal map strength is applied incorrectly #109763

Merged
Brecht Van Lommel merged 7 commits from kaspian.jakobssongmail.com/blender:fix-normals into main 2023-07-17 20:06:50 +02:00
4 changed files with 28 additions and 15 deletions

View File

@ -33,11 +33,16 @@ shader node_normal_map(float Strength = 1.0,
if (getattribute(attr_name, tangent) && getattribute(attr_sign_name, tangent_sign) &&
(!is_smooth || getattribute("geom:normal_map_normal", ninterp)))
{
// apply normal map
/* apply normal map */
vector B = tangent_sign * cross(ninterp, tangent);
/* apply strength */
mcolor[0] *= Strength;
mcolor[1] *= Strength;
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
// transform to world space
/* transform to world space */
Normal = normalize(transform("object", "world", Normal));
}
else {
@ -70,6 +75,6 @@ shader node_normal_map(float Strength = 1.0,
Normal = -Normal;
}
if (Strength != 1.0)
if (Strength != 1.0 && space != "tangent")
Normal = normalize(N + (Normal - N) * max(Strength, 0.0));
}

View File

@ -276,7 +276,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
float3 N;
float strength = stack_load_float(stack, strength_offset);
if (space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
if (sd->object == OBJECT_NONE || (sd->type & PRIMITIVE_TRIANGLE) == 0) {
@ -313,6 +313,9 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
object_inverse_normal_transform(kg, sd, &normal);
}
/* Apply strength in the tangent case. */
color.x *= strength;
color.y *= strength;
/* apply normal map */
float3 B = sign * cross(normal, tangent);
@ -335,6 +338,11 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
object_normal_transform(kg, sd, &N);
else
N = safe_normalize(N);
/* Apply strength in all but tangent space. */
if (strength != 1.0f) {
strength = max(strength, 0.0f);
N = safe_normalize(sd->N + (N - sd->N) * strength);
}
}
/* invert normal for backfacing polygons */
@ -342,13 +350,6 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
N = -N;
}
float strength = stack_load_float(stack, strength_offset);
if (strength != 1.0f) {
strength = max(strength, 0.0f);
N = safe_normalize(sd->N + (N - sd->N) * strength);
}
if (is_zero(N)) {
N = sd->N;
}

View File

@ -1,6 +1,6 @@
#ifdef OBINFO_LIB
void node_normal_map(vec4 tangent, vec3 texnormal, out vec3 outnormal)
void node_normal_map(vec4 tangent, float strength, vec3 texnormal, out vec3 outnormal)
{
if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) {
outnormal = g_data.Ni;
@ -9,6 +9,9 @@ void node_normal_map(vec4 tangent, vec3 texnormal, out vec3 outnormal)
tangent *= (FrontFacing ? 1.0 : -1.0);
vec3 B = tangent.w * cross(g_data.Ni, tangent.xyz) * sign(ObjectInfo.w);
/* Apply strength here instead of in node_normal_map_mix for tangent space. */
texnormal.xy *= strength;
outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * g_data.Ni;
outnormal = normalize(outnormal);
}
@ -26,5 +29,5 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
void node_normal_map_mix(float strength, vec3 newnormal, out vec3 outnormal)
{
outnormal = normalize(mix(g_data.N, newnormal, max(strength, 0.0)));
outnormal = normalize(mix(g_data.N, newnormal, max(0.0, strength)));
}

View File

@ -94,12 +94,15 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
switch (nm->space) {
case SHD_SPACE_TANGENT:
GPU_material_flag_set(mat, GPU_MATFLAG_OBJECT_INFO);
/* We return directly from the node_normal_map as strength
* has already been applied for the tangent case */
GPU_link(mat,
"node_normal_map",
GPU_attribute(mat, CD_TANGENT, nm->uv_map),
strength,
newnormal,
&newnormal);
break;
&out[0].link);
return true;
case SHD_SPACE_OBJECT:
case SHD_SPACE_BLENDER_OBJECT:
GPU_link(mat, "normal_transform_object_to_world", newnormal, &newnormal);
@ -110,6 +113,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
break;
}
/* Final step - mix and apply strength for all other than tangent space. */
GPU_link(mat, "node_normal_map_mix", strength, newnormal, &out[0].link);
return true;