Skip to content

Instantly share code, notes, and snippets.

@romainguy
Created June 1, 2018 20:25
Show Gist options
  • Save romainguy/39d4c1c6aac56623399dcd1e8da68337 to your computer and use it in GitHub Desktop.
Save romainguy/39d4c1c6aac56623399dcd1e8da68337 to your computer and use it in GitHub Desktop.
Anisotropic BRDF
float D_GGX_Anisotropic(float at, float ab, float ToH, float BoH, float NoH) {
// Burley 2012, "Physically-Based Shading at Disney"
float a2 = at * ab;
vec3 d = vec3(ab * ToH, at * BoH, a2 * NoH);
return saturateMediump(a2 * sq(a2 / dot(d, d)) * (1.0 / PI));
}
float V_SmithGGXCorrelated_Anisotropic(float at, float ab, float ToV, float BoV,
float ToL, float BoL, float NoV, float NoL) {
// Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
// TODO: lambdaV can be pre-computed for all the lights, it should be moved out of this function
float lambdaV = NoL * length(vec3(at * ToV, ab * BoV, NoL));
float lambdaL = NoV * length(vec3(at * ToL, ab * BoL, NoV));
float v = 0.5 / (lambdaV + lambdaL);
return saturateMediump(v);
}
vec3 F_Schlick(const vec3 f0, float f90, float VoH) {
// Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
float f = pow5(1.0 - VoH);
return f + f0 * (f90 - f);
}
float distributionAnisotropic(float at, float ab, float ToH, float BoH, float NoH) {
return D_GGX_Anisotropic(at, ab, ToH, BoH, NoH);
}
float visibilityAnisotropic(float linearRoughness, float at, float ab,
float ToV, float BoV, float ToL, float BoL, float NoV, float NoL) {
return V_SmithGGXCorrelated_Anisotropic(at, ab, ToV, BoV, ToL, BoL, NoV, NoL);
}
vec3 fresnel(const vec3 f0, float LoH) {
return F_Schlick(f0, 1.0, LoH);
}
vec3 anisotropicLobe(const PixelParams pixel, const Light light, const vec3 h,
float NoV, float NoL, float NoH, float LoH) {
vec3 l = light.l;
vec3 t = pixel.anisotropicT;
vec3 b = pixel.anisotropicB;
vec3 v = shading_view;
float ToV = dot(t, v);
float BoV = dot(b, v);
float ToL = dot(t, l);
float BoL = dot(b, l);
float ToH = dot(t, h);
float BoH = dot(b, h);
// Anisotropic parameters: at and ab are the roughness along the tangent and bitangent
// to simplify materials, we derive them from a single roughness parameter
// Kulla 2017, "Revisiting Physically Based Shading at Imageworks"
float at = max(pixel.linearRoughness * (1.0 + pixel.anisotropy), MIN_LINEAR_ROUGHNESS);
float ab = max(pixel.linearRoughness * (1.0 - pixel.anisotropy), MIN_LINEAR_ROUGHNESS);
// specular anisotropic BRDF
float D = distributionAnisotropic(at, ab, ToH, BoH, NoH);
float V = visibilityAnisotropic(pixel.linearRoughness, at, ab, ToV, BoV, ToL, BoL, NoV, NoL);
vec3 F = fresnel(pixel.f0, LoH);
return (D * V) * F;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment