Cycles: Replace bump correction algorithm to better respect normal maps
The new correction avoids washed out areas near the shadow terminator, preserving more detail from normal and bump maps. It implements the method from the paper "A Microfacet-Based Shadowing Function to Solve the Bump Terminator Problem" by Alejandro Conty Estevez, Pascal Lecocq, and Clifford Stein. Pull Request: https://projects.blender.org/blender/blender/pulls/135380
This commit is contained in:
committed by
Brecht Van Lommel
parent
8b831be87f
commit
5e2afb3f6f
@@ -57,27 +57,24 @@ ccl_device_inline float bsdf_get_roughness_pass_squared(const ccl_private Shader
|
||||
return bsdf_get_specular_roughness_squared(sc);
|
||||
}
|
||||
|
||||
/* An additional term to smooth illumination on grazing angles when using bump mapping.
|
||||
* Based on "Taming the Shadow Terminator" by Matt Jen-Yuan Chiang,
|
||||
* Yining Karl Li and Brent Burley. */
|
||||
/* An additional term to smooth illumination on grazing angles when using bump mapping
|
||||
* based on "A Microfacet-Based Shadowing Function to Solve the Bump Terminator Problem"
|
||||
* by Alejandro Conty Estevez, Pascal Lecocq, and Clifford Stein. It preserves detail
|
||||
* close to the shadow terminator, and doesn't "wash out" intermediate bumps using a
|
||||
* Cook-Torrance GGX function for shading. */
|
||||
ccl_device_inline float bump_shadowing_term(const int shader_flag,
|
||||
float3 Ng,
|
||||
const float3 N,
|
||||
float3 I)
|
||||
{
|
||||
const float cosNgI = dot(Ng, I);
|
||||
const float cosNgN = dot(Ng, N);
|
||||
const float cosNI = dot(N, I);
|
||||
if (cosNI < 0.0f) {
|
||||
Ng = -Ng;
|
||||
}
|
||||
const float g = safe_divide(dot(Ng, I), cosNI * dot(Ng, N));
|
||||
|
||||
/* If the incoming light is on the unshadowed side, return full brightness. */
|
||||
if (g >= 1.0f) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/* If the incoming light points away from the surface, return black. */
|
||||
if (g < 0.0f) {
|
||||
/* dot(Ng, I) * dot(Ng, N) tells us if I and N are on the same side of the actual geometry.
|
||||
* If incoming(I) and normal(N) are on the same side we reject refractions, dot(N, I) < 0.
|
||||
* If they are on different sides we reject reflections, dot(N, I) > 0. */
|
||||
if (cosNgI * cosNgN * cosNI < 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -86,9 +83,22 @@ ccl_device_inline float bump_shadowing_term(const int shader_flag,
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/* Get absolute incoming and shader normal deviation from geometric normal, then clamp. */
|
||||
const float cos_i = fabsf(cosNgI);
|
||||
const float cos_d = fabsf(cosNgN);
|
||||
if (cos_d >= 1.0f || cos_i >= 1.0f) {
|
||||
return 1.0f;
|
||||
}
|
||||
if (cos_i < 1e-6f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/* Get GGX shading values for final smoothing. */
|
||||
const float tan2_d = 1.0f / sqr(cos_d) - 1.0f;
|
||||
const float bump_alpha2 = saturatef(0.125f * tan2_d);
|
||||
|
||||
/* Return smoothed value to avoid discontinuity at perpendicular angle. */
|
||||
const float g2 = sqr(g);
|
||||
return -g2 * g + g2 + g;
|
||||
return bsdf_G<MicrofacetType::GGX>(bump_alpha2, cos_i);
|
||||
}
|
||||
|
||||
ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multiplier)
|
||||
|
||||
Submodule tests/data updated: 92d6d4b38f...14a8111f11
Reference in New Issue
Block a user