pex-renderer
Version:
Physically Based Renderer for Pex
70 lines (57 loc) • 2.74 kB
JavaScript
module.exports = /* glsl */ `
uniform sampler2D uReflectionMap;
uniform int uReflectionMapEncoding;
vec3 getPrefilteredReflection(vec3 reflected, float roughness) {
// float lod = pow(roughness, 2.0) * MAX_MIPMAP_LEVEL; // TODO: verify reflection probe blurring code
float lod = pow(roughness, 1.5) * MAX_MIPMAP_LEVEL;
float upLod = floor(lod);
float downLod = ceil(lod);
vec3 a = decode(texture2D(uReflectionMap, envMapOctahedral(reflected, 0.0, upLod)), uReflectionMapEncoding).rgb;
vec3 b = decode(texture2D(uReflectionMap, envMapOctahedral(reflected, 0.0, downLod)), uReflectionMapEncoding).rgb;
return mix(a, b, lod - upLod);
}
vec3 EnvBRDFApprox( vec3 specularColor, float roughness, float NoV ) {
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022 );
const vec4 c1 = vec4( 1.0, 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;
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
return specularColor * AB.x + AB.y;
}
// https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/clearcoat
void evaluateClearCoatIBL(const PBRData data, float ao, inout vec3 Fd, inout vec3 Fr) {
float clearCoatNoV = abs(dot(data.clearCoatNormal, data.viewWorld)) + FLT_EPS;
vec3 clearCoatR = reflect(-data.viewWorld, data.clearCoatNormal);
float clearCoatNoV = data.NdotV;
vec3 clearCoatR = data.reflectionWorld;
// The clear coat layer assumes an IOR of 1.5 (4% reflectance)
float Fc = F_Schlick(0.04, 1.0, clearCoatNoV) * uClearCoat;
float attenuation = 1.0 - Fc;
Fr *= (attenuation * attenuation);
Fr += getPrefilteredReflection(clearCoatR, uClearCoatRoughness) * (ao * Fc);
Fd *= attenuation;
}
void EvaluateLightProbe(inout PBRData data, float ao) {
// TODO: energyCompensation
float energyCompensation = 1.0;
vec3 diffuseIrradiance = getIrradiance(data.normalWorld, uReflectionMap, uReflectionMapEncoding);
vec3 Fd = data.diffuseColor * diffuseIrradiance * ao;
vec3 specularReflectance = EnvBRDFApprox(data.f0, data.roughness, data.NdotV);
vec3 prefilteredRadiance = getPrefilteredReflection(data.reflectionWorld, data.roughness);
vec3 Fr = specularReflectance * prefilteredRadiance * ao;
Fr *= energyCompensation;
evaluateClearCoatIBL(data, ao, Fd, Fr);
data.indirectDiffuse += Fd;
data.indirectSpecular += Fr;
}
`