From 7f33a0eaf5a14720d5ed920c795adf7fab2f974d Mon Sep 17 00:00:00 2001 From: Szymon Nowakowski Date: Sun, 13 Aug 2023 23:52:15 +0200 Subject: [PATCH] Deduplicate lighting shader --- src/shader.ts | 59 +++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/src/shader.ts b/src/shader.ts index dcf676d..66532d8 100644 --- a/src/shader.ts +++ b/src/shader.ts @@ -237,6 +237,26 @@ fn toneMapAcesNarkowicz(color: vec3) -> vec3 { return saturate((color * (A * color + B)) / (color * (C * color + D) + E)); } +fn lightOutgoingRadiance( + viewDirectionVS: vec3, actualNormalVS: vec3, dotNV: f32, + baseColor: vec3, alpha: f32, metallic: f32, f0: vec3, + incomingRadiance: vec3, lightDirectionVS: vec3, +) -> vec3 { + let halfVectorVS = normalize(lightDirectionVS + viewDirectionVS); + let dotVH = saturate(dot(viewDirectionVS, halfVectorVS)); + let dotNH = saturate(dot(actualNormalVS, halfVectorVS)); + let dotNL = saturate(dot(actualNormalVS, lightDirectionVS)); + + let fresnel = fresnelSchlick(dotVH, f0); + let visibility = visibilityGGX(dotNL, dotNV, alpha); + let distribution = distributionGGX(dotNH, alpha); + + let scatteredFactor = (1.0 - fresnel) * (1.0 - metallic) * baseColor * INV_PI; + let reflectedFactor = fresnel * visibility * distribution; + + return (scatteredFactor + reflectedFactor) * incomingRadiance * dotNL; +} + fn screenSpaceMatrixTStoVS(positionVS: vec3, normalVS: vec3, texCoord: vec2) -> mat3x3 { let q0 = dpdx(positionVS); let q1 = dpdy(positionVS); @@ -344,43 +364,26 @@ fn frag(fragment: Varyings) -> @location(0) vec2 { let lightDirectionVS = normalize(lightPositionVS - positionVS); let lightDistance = distance(positionVS, lightPositionVS); let lightAttenuation = 1.0 / (lightDistance * lightDistance); - let halfVectorVS = normalize(lightDirectionVS + viewDirectionVS); + let incomingRadiance = light.color * lightAttenuation; - let dotVH = saturate(dot(viewDirectionVS, halfVectorVS)); - let dotNH = saturate(dot(actualNormalVS, halfVectorVS)); - let dotNL = saturate(dot(actualNormalVS, lightDirectionVS)); - - let incomingRadiance = light.color * attenuation; - - let fresnel = fresnelSchlick(dotVH, f0); - let visibility = visibilityGGX(dotNL, dotNV, alpha); - let distribution = distributionGGX(dotNH, alpha); - - let scatteredFactor = (1.0 - fresnel) * (1.0 - metallic) * baseColor * INV_PI; - let reflectedFactor = fresnel * visibility * distribution; - - outgoingRadiance += (scatteredFactor + reflectedFactor) * incomingRadiance * dotNL; + outgoingRadiance += lightOutgoingRadiance( + viewDirectionVS, actualNormalVS, dotNV, + baseColor, alpha, metallic, f0, + incomingRadiance, lightDirectionVS, + ); } for (var i: u32 = 0; i < _Global.directionalLightCount; ++i) { let light = _DirectionalLights[i]; let lightDirectionVS = normalize((_Global.matrixWStoVS * vec4(light.directionWS, 0.0)).xyz); - let halfVectorVS = normalize(lightDirectionVS + viewDirectionVS); - - let dotVH = saturate(dot(viewDirectionVS, halfVectorVS)); - let dotNH = saturate(dot(actualNormalVS, halfVectorVS)); - let incomingRadiance = light.color; - let fresnel = fresnelSchlick(dotVH, f0); - let visibility = visibilityGGX(dotNL, dotNV, alpha); - let distribution = distributionGGX(dotNH, alpha); - - let scatteredFactor = (1.0 - fresnel) * (1.0 - metallic) * baseColor * INV_PI; - let reflectedFactor = fresnel * visibility * distribution; - - outgoingRadiance += (scatteredFactor + reflectedFactor) * incomingRadiance * dotNL; + outgoingRadiance += lightOutgoingRadiance( + viewDirectionVS, actualNormalVS, dotNV, + baseColor, alpha, metallic, f0, + incomingRadiance, lightDirectionVS, + ); } outgoingRadiance += _Global.ambientLight * baseColor * occlusion;