Fix #145254: Cycles normal map node strength wrong results with displacement
Can not use tangent space interpolation in this case, as the tangent space is for the undisplaced normal. Pull Request: https://projects.blender.org/blender/blender/pulls/145273
This commit is contained in:
@@ -13,6 +13,7 @@ shader node_normal_map(float Strength = 1.0,
|
||||
{
|
||||
color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
|
||||
int is_backfacing = backfacing();
|
||||
int linear_interpolate_strength = 0;
|
||||
|
||||
if (space == "tangent") {
|
||||
vector tangent;
|
||||
@@ -20,8 +21,25 @@ shader node_normal_map(float Strength = 1.0,
|
||||
float tangent_sign;
|
||||
float is_smooth = 0.0;
|
||||
|
||||
if (!getattribute(attr_name, tangent) || !getattribute(attr_sign_name, tangent_sign)) {
|
||||
Normal = N;
|
||||
return;
|
||||
}
|
||||
|
||||
getattribute("geom:is_smooth", is_smooth);
|
||||
if (!is_smooth) {
|
||||
if (is_smooth) {
|
||||
if (getattribute("undisplaced_N", ninterp)) {
|
||||
/* Can't interpolate in tangent space as the displaced normal is not used
|
||||
* for the tangent frame. */
|
||||
linear_interpolate_strength = 1;
|
||||
}
|
||||
else if (getattribute("geom:normal_map_normal", ninterp)) {
|
||||
}
|
||||
else {
|
||||
ninterp = N;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ninterp = normalize(transform("world", "object", Ng));
|
||||
|
||||
/* the normal is already inverted, which is too soon for the math here */
|
||||
@@ -30,46 +48,44 @@ shader node_normal_map(float Strength = 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
// get _unnormalized_ interpolated normal and tangent
|
||||
if (getattribute(attr_name, tangent) && getattribute(attr_sign_name, tangent_sign) &&
|
||||
(!is_smooth || getattribute("geom:normal_map_normal", ninterp)))
|
||||
{
|
||||
/* apply normal map */
|
||||
vector B = tangent_sign * cross(ninterp, tangent);
|
||||
/* apply normal map */
|
||||
vector B = tangent_sign * cross(ninterp, tangent);
|
||||
|
||||
/* apply strength */
|
||||
/* apply strength */
|
||||
if (!linear_interpolate_strength) {
|
||||
mcolor[0] *= Strength;
|
||||
mcolor[1] *= Strength;
|
||||
mcolor[2] = mix(1.0, mcolor[2], clamp(Strength, 0.0, 1.0));
|
||||
|
||||
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
|
||||
|
||||
/* transform to world space */
|
||||
Normal = normalize(transform("object", "world", Normal));
|
||||
}
|
||||
else {
|
||||
Normal = normal(0, 0, 0);
|
||||
|
||||
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
|
||||
|
||||
/* transform to world space */
|
||||
Normal = normalize(transform("object", "world", Normal));
|
||||
}
|
||||
else {
|
||||
linear_interpolate_strength = 1;
|
||||
|
||||
if (space == "object") {
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
}
|
||||
else if (space == "object") {
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
else if (space == "world") {
|
||||
Normal = normalize(vector(mcolor));
|
||||
}
|
||||
else if (space == "blender_object") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
else if (space == "world") {
|
||||
Normal = normalize(vector(mcolor));
|
||||
}
|
||||
else if (space == "blender_object") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
else if (space == "blender_world") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
Normal = normalize(transform("object", "world", vector(mcolor)));
|
||||
}
|
||||
else if (space == "blender_world") {
|
||||
/* strange blender convention */
|
||||
mcolor[1] = -mcolor[1];
|
||||
mcolor[2] = -mcolor[2];
|
||||
|
||||
Normal = normalize(vector(mcolor));
|
||||
Normal = normalize(vector(mcolor));
|
||||
}
|
||||
}
|
||||
|
||||
/* invert normal for backfacing polygons */
|
||||
@@ -77,6 +93,7 @@ shader node_normal_map(float Strength = 1.0,
|
||||
Normal = -Normal;
|
||||
}
|
||||
|
||||
if (Strength != 1.0 && space != "tangent")
|
||||
if (linear_interpolate_strength && Strength != 1.0) {
|
||||
Normal = normalize(N + (Normal - N) * max(Strength, 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +337,8 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
||||
const bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
|
||||
float3 N;
|
||||
float strength = stack_load_float(stack, strength_offset);
|
||||
bool linear_interpolate_strength = false;
|
||||
|
||||
if (space == NODE_NORMAL_MAP_TANGENT) {
|
||||
/* tangent space */
|
||||
if (sd->object == OBJECT_NONE || (sd->type & PRIMITIVE_TRIANGLE) == 0) {
|
||||
@@ -366,6 +368,9 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
||||
if (attr_undisplaced_normal.offset != ATTR_STD_NOT_FOUND) {
|
||||
normal =
|
||||
primitive_surface_attribute<float3>(kg, sd, attr_undisplaced_normal, false, false).val;
|
||||
/* Can't interpolate in tangent space as the displaced normal is not used
|
||||
* for the tangent frame. */
|
||||
linear_interpolate_strength = true;
|
||||
}
|
||||
else {
|
||||
normal = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
|
||||
@@ -382,9 +387,11 @@ 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;
|
||||
color.z = mix(1.0f, color.z, saturatef(strength));
|
||||
if (!linear_interpolate_strength) {
|
||||
color.x *= strength;
|
||||
color.y *= strength;
|
||||
color.z = mix(1.0f, color.z, saturatef(strength));
|
||||
}
|
||||
|
||||
/* apply normal map */
|
||||
const float3 B = sign * cross(normal, tangent);
|
||||
@@ -399,6 +406,8 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
||||
}
|
||||
}
|
||||
else {
|
||||
linear_interpolate_strength = true;
|
||||
|
||||
/* strange blender convention */
|
||||
if (space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
|
||||
color.y = -color.y;
|
||||
@@ -419,12 +428,12 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
|
||||
if (is_backfacing) {
|
||||
N = -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);
|
||||
}
|
||||
/* Use simple linear linear interpolation if we can't do it in tangent space. */
|
||||
if (linear_interpolate_strength && strength != 1.0f) {
|
||||
strength = max(strength, 0.0f);
|
||||
N = safe_normalize(sd->N + (N - sd->N) * strength);
|
||||
}
|
||||
|
||||
if (is_zero(N) || !isfinite_safe(N)) {
|
||||
|
||||
Reference in New Issue
Block a user