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:
Clément Foucault
2022-05-09 19:20:39 +02:00
parent f4827d08bc
commit bfa1c077cb
8 changed files with 21 additions and 9 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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")

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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));
}