Fix T97983 EEVEE: Tangent Normal of Curves info behaves differently in Eevee
Curve tangent was correctly mistaken with curve normal. This patch fixes the name of the output in the glsl function and make curve attributes more explicit (with `curve_` prefix). This also improve the normal computation by making it per pixel to match cycles. Also ports the changes to eevee-next.
This commit is contained in:
@@ -112,6 +112,7 @@ GlobalData init_globals(void)
|
||||
surf.N = -surf.N;
|
||||
}
|
||||
# ifdef HAIR_SHADER
|
||||
vec3 V = cameraVec(surf.P);
|
||||
/* Shade as a cylinder. */
|
||||
vec3 B = normalize(cross(worldNormal, hairTangent));
|
||||
float cos_theta;
|
||||
@@ -125,7 +126,10 @@ GlobalData init_globals(void)
|
||||
}
|
||||
float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
|
||||
surf.N = safe_normalize(worldNormal * sin_theta + B * cos_theta);
|
||||
surf.T = hairTangent;
|
||||
surf.curve_T = -hairTangent;
|
||||
/* Costly, but follows cycles per pixel tangent space (not following curve shape). */
|
||||
surf.curve_B = cross(V, surf.curve_T);
|
||||
surf.curve_N = safe_normalize(cross(surf.curve_T, surf.curve_B));
|
||||
surf.is_strand = true;
|
||||
surf.hair_time = hairTime;
|
||||
surf.hair_thickness = hairThickness;
|
||||
@@ -134,7 +138,7 @@ GlobalData init_globals(void)
|
||||
surf.barycentric_coords = hair_resolve_barycentric(hairBary);
|
||||
# endif
|
||||
# else
|
||||
surf.T = vec3(0.0);
|
||||
surf.curve_T = surf.curve_B = surf.curve_N = vec3(0.0);
|
||||
surf.is_strand = false;
|
||||
surf.hair_time = 0.0;
|
||||
surf.hair_thickness = 0.0;
|
||||
|
||||
@@ -18,7 +18,7 @@ void main()
|
||||
ViewMatrixInverse[3].xyz,
|
||||
ViewMatrixInverse[2].xyz,
|
||||
interp.P,
|
||||
T,
|
||||
interp.curves_tangent,
|
||||
interp.curves_binormal,
|
||||
interp.curves_time,
|
||||
interp.curves_thickness,
|
||||
|
||||
@@ -42,6 +42,12 @@ void init_globals_curves()
|
||||
float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
|
||||
g_data.N = normalize(interp.N * sin_theta + interp.curves_binormal * cos_theta);
|
||||
|
||||
/* Costly, but follows cycles per pixel tangent space (not following curve shape). */
|
||||
vec3 V = cameraVec(g_data.P);
|
||||
g_data.curve_T = -interp.curves_tangent;
|
||||
g_data.curve_B = cross(V, g_data.curve_T);
|
||||
g_data.curve_N = safe_normalize(cross(g_data.curve_T, g_data.curve_B));
|
||||
|
||||
g_data.is_strand = true;
|
||||
g_data.hair_time = interp.curves_time;
|
||||
g_data.hair_thickness = interp.curves_thickness;
|
||||
@@ -94,6 +100,7 @@ void init_interface()
|
||||
interp.P = vec3(0.0);
|
||||
interp.N = vec3(0.0);
|
||||
interp.barycentric_coords = vec2(0.0);
|
||||
interp.curves_tangent = vec3(0.0);
|
||||
interp.curves_binormal = vec3(0.0);
|
||||
interp.curves_time = 0.0;
|
||||
interp.curves_time_width = 0.0;
|
||||
|
||||
@@ -54,6 +54,7 @@ GPU_SHADER_INTERFACE_INFO(eevee_surf_iface, "interp")
|
||||
.smooth(Type::VEC3, "P")
|
||||
.smooth(Type::VEC3, "N")
|
||||
.smooth(Type::VEC2, "barycentric_coords")
|
||||
.smooth(Type::VEC3, "curves_tangent")
|
||||
.smooth(Type::VEC3, "curves_binormal")
|
||||
.smooth(Type::FLOAT, "curves_time")
|
||||
.smooth(Type::FLOAT, "curves_time_width")
|
||||
|
||||
@@ -191,8 +191,8 @@ struct GlobalData {
|
||||
vec3 N;
|
||||
/** Geometric Normal. */
|
||||
vec3 Ng;
|
||||
/** Surface default Tangent. */
|
||||
vec3 T;
|
||||
/** Curve Tangent Space. */
|
||||
vec3 curve_T, curve_B, curve_N;
|
||||
/** Barycentric coordinates. */
|
||||
vec2 barycentric_coords;
|
||||
vec3 barycentric_dists;
|
||||
|
||||
@@ -18,7 +18,7 @@ void node_geometry(vec3 orco,
|
||||
true_normal = g_data.Ng;
|
||||
|
||||
if (g_data.is_strand) {
|
||||
tangent = g_data.T;
|
||||
tangent = g_data.curve_T;
|
||||
}
|
||||
else {
|
||||
tangent_orco_z(orco, orco);
|
||||
|
||||
@@ -40,7 +40,7 @@ void node_bsdf_hair_principled(vec4 color,
|
||||
hair_data.color = color.rgb;
|
||||
hair_data.offset = offset;
|
||||
hair_data.roughness = vec2(0.0);
|
||||
hair_data.T = g_data.T;
|
||||
hair_data.T = g_data.curve_B;
|
||||
|
||||
result = closure_eval(hair_data);
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ void node_hair_info(float hair_length,
|
||||
out float intercept,
|
||||
out float out_length,
|
||||
out float thickness,
|
||||
out vec3 tangent,
|
||||
out vec3 normal,
|
||||
out float random)
|
||||
{
|
||||
is_strand = float(g_data.is_strand);
|
||||
intercept = g_data.hair_time;
|
||||
thickness = g_data.hair_thickness;
|
||||
out_length = hair_length;
|
||||
tangent = g_data.T;
|
||||
normal = g_data.curve_N;
|
||||
/* TODO: could be precomputed per strand instead. */
|
||||
random = wang_hash_noise(uint(g_data.hair_strand_id));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user