Files
LNXSDK/leenkx/Shaders/std/brdf.glsl

89 lines
2.5 KiB
Plaintext
Raw Normal View History

2025-01-22 16:18:30 +01:00
#ifndef _BRDF_GLSL_
#define _BRDF_GLSL_
// Constants
//const float PI = 3.1415926535;
// Fresnel-Schlick with optimized exponential approximation
2025-01-22 16:18:30 +01:00
vec3 f_schlick(const vec3 f0, const float vh) {
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
}
float v_smithschlick(const float nl, const float nv, const float a) {
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
}
float d_ggx(const float nh, const float a) {
float a2 = a * a;
float denom = nh * nh * (a2 - 1.0) + 1.0;
denom = max(denom * denom, 2e-6);
return a2 / (PI * denom);
2025-01-22 16:18:30 +01:00
}
float getMipFromRoughness(const float roughness, const float numMipmaps) {
// First mipmap level = roughness 0, last = roughness = 1
return roughness * numMipmaps;
2025-01-22 16:18:30 +01:00
}
vec3 specularBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness)
{
vec3 H = normalize(V + L);
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.0);
float NdotH = max(dot(N, H), 0.0);
float VdotH = max(dot(V, H), 0.0);
2025-01-22 16:18:30 +01:00
float alpha = roughness * roughness;
float D = d_ggx(NdotH, alpha);
2025-01-22 16:18:30 +01:00
float k = alpha / 2.0;
float G_V = NdotV / (NdotV * (1.0 - k) + k + 1e-5);
float G_L = NdotL / (NdotL * (1.0 - k) + k + 1e-5);
float G = G_V * G_L;
vec3 F = f_schlick(F0, VdotH);
2025-01-22 16:18:30 +01:00
return F * D * G / max(4.0 * NdotL * NdotV, 1e-5);
2025-01-22 16:18:30 +01:00
}
vec3 burleyDiffuseBRDF(vec3 N, vec3 V, vec3 L, vec3 albedo, float roughness)
{
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.0);
float LdotH = max(dot(L, normalize(L + V)), 0.0);
float FD90 = 0.5 + 2.0 * LdotH * LdotH * roughness;
float FL = pow(1.0 - NdotL, 5.0);
float FV = pow(1.0 - NdotV, 5.0);
float diffuse = (1.0 + (FD90 - 1.0) * FL) * (1.0 + (FD90 - 1.0) * FV);
return albedo * (1.0 / PI) * diffuse * NdotL;
2025-01-22 16:18:30 +01:00
}
// Energy-conserving material albedo (fades out for metals)
2025-01-22 16:18:30 +01:00
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
return baseColor * (1.0 - metalness);
2025-01-22 16:18:30 +01:00
}
// Metal-aware F0 blending
vec3 surfaceF0(vec3 baseColor, float metalness) {
2025-01-22 16:18:30 +01:00
return mix(vec3(0.04), baseColor, metalness);
}
// LUT-based approximation of IBL BRDF (Unreal-style)
vec2 EnvBRDFApprox(float Roughness, float NoV) {
const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04);
vec4 r = Roughness * c0 + c1;
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
return vec2(-1.04, 1.04) * a004 + r.zw;
2025-01-22 16:18:30 +01:00
}
vec3 IBLSpecularApprox(vec3 specColor, float roughness, float NoV) {
vec2 brdf = EnvBRDFApprox(roughness, NoV);
return specColor * brdf.x + brdf.y;
2025-01-22 16:18:30 +01:00
}
#endif