Skip to content

Commit 4d0a2d0

Browse files
committed
add bent normals-based IBL anisotropy rendering.
1 parent 18a1b7a commit 4d0a2d0

3 files changed

Lines changed: 34 additions & 3 deletions

File tree

libraries/pbrlib/genglsl/lib/mx_environment_fis.glsl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distributio
55
// Generate tangent frame.
66
X = normalize(X - dot(X, N) * N);
77
vec3 Y = cross(N, X);
8-
mat3 tangentToWorld = mat3(X, Y, N);
8+
vec3 bentNormal = mx_bent_normal_anisotropy(N, V, X, Y, alpha);
9+
X = normalize(X - dot(X, bentNormal) * bentNormal);
10+
Y = cross(bentNormal, X);
11+
mat3 tangentToWorld = mat3(X, Y, bentNormal);
912

1013
// Transform the view vector to tangent space.
11-
V = vec3(dot(V, X), dot(V, Y), dot(V, N));
14+
V = vec3(dot(V, X), dot(V, Y), dot(V, bentNormal));
1215

1316
// Compute derived properties.
1417
float NdotV = clamp(V.z, M_FLOAT_EPS, 1.0);

libraries/pbrlib/genglsl/lib/mx_environment_prefilter.glsl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ float mx_latlong_alpha_to_lod(float alpha)
1010
vec3 mx_environment_radiance(vec3 N, vec3 V, vec3 X, vec2 alpha, int distribution, FresnelData fd)
1111
{
1212
N = mx_forward_facing_normal(N, V);
13-
vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, N, fd.ior.x) : -reflect(V, N);
13+
X = normalize(X - dot(X, N) * N);
14+
vec3 Y = cross(N, X);
15+
vec3 bentNormal = mx_bent_normal_anisotropy(N, V, X, Y, alpha);
16+
vec3 L = fd.refraction ? mx_refraction_solid_sphere(-V, N, fd.ior.x) : -reflect(V, bentNormal);
1417

1518
float NdotV = clamp(dot(N, V), M_FLOAT_EPS, 1.0);
1619

libraries/pbrlib/genglsl/lib/mx_microfacet_specular.glsl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,31 @@ float mx_average_alpha(vec2 alpha)
192192
return sqrt(alpha.x * alpha.y);
193193
}
194194

195+
// Approximate anisotropic IBL with a bent normal from alpha.x / alpha.y.
196+
// https://google.github.io/filament/Filament.md.html Section Anisotropy
197+
vec3 mx_bent_normal_anisotropy(vec3 N, vec3 V, vec3 X, vec3 Y, vec2 alpha)
198+
{
199+
float maxAlpha = max(max(alpha.x, alpha.y), M_FLOAT_EPS);
200+
float minOverMax = min(alpha.x, alpha.y) / maxAlpha;
201+
float anisotropy = 1.0 - clamp(minOverMax, 0.0, 1.0);
202+
float anisotropySign = (alpha.x >= alpha.y) ? 1.0 : -1.0;
203+
float signedAnisotropy = anisotropy * anisotropySign;
204+
205+
vec3 anisotropicDirection = (signedAnisotropy >= 0.0) ? Y : X;
206+
vec3 anisotropicTangent = cross(anisotropicDirection, V);
207+
float tangentLenSq = dot(anisotropicTangent, anisotropicTangent);
208+
vec3 anisotropicNormal = (tangentLenSq > M_FLOAT_EPS) ?
209+
normalize(cross(anisotropicTangent, anisotropicDirection)) : N;
210+
211+
float roughness = clamp(sqrt(mx_average_alpha(alpha)), 0.0, 1.0);
212+
float bend = abs(signedAnisotropy) * (1.0 - roughness);
213+
float normalWeight = 1.0 - bend;
214+
normalWeight *= normalWeight;
215+
normalWeight *= normalWeight;
216+
217+
return normalize(mix(anisotropicNormal, N, normalWeight));
218+
}
219+
195220
// Convert a real-valued index of refraction to normal-incidence reflectivity.
196221
float mx_ior_to_f0(float ior)
197222
{

0 commit comments

Comments
 (0)