| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- // Light Computing
- struct lightingInfo
- {
- vec3 diffuse;
- #ifdef SPECULARTERM
- vec3 specular;
- #endif
- };
- struct pointLightingInfo
- {
- vec3 lightOffset;
- float lightDistanceSquared;
- float attenuation;
- };
- struct spotLightingInfo
- {
- vec3 lightOffset;
- float lightDistanceSquared;
- vec3 directionToLightCenterW;
- float attenuation;
- };
- float computeDistanceLightFalloff_Standard(vec3 lightOffset, float range)
- {
- return max(0., 1.0 - length(lightOffset) / range);
- }
- float computeDistanceLightFalloff_Physical(float lightDistanceSquared)
- {
- return 1.0 / ((lightDistanceSquared + 0.001));
- }
- float computeDistanceLightFalloff_GLTF(float lightDistanceSquared, float inverseSquaredRange)
- {
- const float minDistanceSquared = 0.01*0.01;
- float lightDistanceFalloff = 1.0 / (max(lightDistanceSquared, minDistanceSquared));
- float factor = lightDistanceSquared * inverseSquaredRange;
- float attenuation = clamp(1.0 - factor * factor, 0., 1.);
- attenuation *= attenuation;
- // Smooth attenuation of the falloff defined by the range.
- lightDistanceFalloff *= attenuation;
-
- return lightDistanceFalloff;
- }
- float computeDistanceLightFalloff(vec3 lightOffset, float lightDistanceSquared, float range, float inverseSquaredRange)
- {
- #ifdef USEPHYSICALLIGHTFALLOFF
- return computeDistanceLightFalloff_Physical(lightDistanceSquared);
- #elif defined(USEGLTFLIGHTFALLOFF)
- return computeDistanceLightFalloff_GLTF(lightDistanceSquared, inverseSquaredRange);
- #else
- return computeDistanceLightFalloff_Standard(lightOffset, range);
- #endif
- }
- float computeDirectionalLightFalloff_Standard(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle, float exponent)
- {
- float falloff = 0.0;
- float cosAngle = max(0.000000000000001, dot(-lightDirection, directionToLightCenterW));
- if (cosAngle >= cosHalfAngle)
- {
- falloff = max(0., pow(cosAngle, exponent));
- }
-
- return falloff;
- }
- float computeDirectionalLightFalloff_Physical(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle)
- {
- const float kMinusLog2ConeAngleIntensityRatio = 6.64385618977; // -log2(0.01)
- // Calculate a Spherical Gaussian (von Mises-Fisher distribution, not angle-based Gaussian) such that the peak is in the light direction,
- // and the value at the nominal cone angle is 1% of the peak. Because we want the distribution to decay from unity (100%)
- // at the peak direction (dot product = 1) down to 1% at the nominal cone cutoff (dot product = cosAngle)
- // the falloff rate expressed in terms of the base-two dot product is therefore -log2(ConeAngleIntensityRatio) / (1.0 - cosAngle).
- // Note that the distribution is unnormalised in that peak density is unity, rather than the total energy is unity.
- float concentrationKappa = kMinusLog2ConeAngleIntensityRatio / (1.0 - cosHalfAngle);
- // Evaluate spherical gaussian for light directional falloff for spot light type (note: spot directional falloff;
- // not directional light type)
- vec4 lightDirectionSpreadSG = vec4(-lightDirection * concentrationKappa, -concentrationKappa);
- float falloff = exp2(dot(vec4(directionToLightCenterW, 1.0), lightDirectionSpreadSG));
- return falloff;
- }
- float computeDirectionalLightFalloff_GLTF(vec3 lightDirection, vec3 directionToLightCenterW, float lightAngleScale, float lightAngleOffset)
- {
- // On the CPU
- // float lightAngleScale = 1.0 f / max (0.001f, ( cosInner - cosOuter ));
- // float lightAngleOffset = -cosOuter * angleScale;
- float cd = dot(-lightDirection, directionToLightCenterW);
- float falloff = clamp(cd * lightAngleScale + lightAngleOffset, 0., 1.);
- // smooth the transition
- falloff *= falloff;
- return falloff;
- }
- float computeDirectionalLightFalloff(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle, float exponent, float lightAngleScale, float lightAngleOffset)
- {
- #ifdef USEPHYSICALLIGHTFALLOFF
- return computeDirectionalLightFalloff_Physical(lightDirection, directionToLightCenterW, cosHalfAngle);
- #elif defined(USEGLTFLIGHTFALLOFF)
- return computeDirectionalLightFalloff_GLTF(lightDirection, directionToLightCenterW, lightAngleScale, lightAngleOffset);
- #else
- return computeDirectionalLightFalloff_Standard(lightDirection, directionToLightCenterW, cosHalfAngle, exponent);
- #endif
- }
- pointLightingInfo computePointLightingInfo(vec4 lightData) {
- pointLightingInfo result;
- result.lightOffset = lightData.xyz - vPositionW;
- result.lightDistanceSquared = dot(result.lightOffset, result.lightOffset);
- return result;
- }
- spotLightingInfo computeSpotLightingInfo(vec4 lightData) {
- spotLightingInfo result;
- result.lightOffset = lightData.xyz - vPositionW;
- result.directionToLightCenterW = normalize(result.lightOffset);
- result.lightDistanceSquared = dot(result.lightOffset, result.lightOffset);
- return result;
- }
- lightingInfo computePointLighting(pointLightingInfo info, vec3 viewDirectionW, vec3 vNormal, vec3 diffuseColor, float lightRadius, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, out float NdotL) {
- lightingInfo result;
- float lightDistance = sqrt(info.lightDistanceSquared);
- vec3 lightDirection = normalize(info.lightOffset);
-
- // Roughness
- roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
-
- // diffuse
- vec3 H = normalize(viewDirectionW + lightDirection);
- NdotL = clamp(dot(vNormal, lightDirection), 0.00000000001, 1.0);
- float VdotH = clamp(dot(viewDirectionW, H), 0.0, 1.0);
- float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
- result.diffuse = diffuseTerm * diffuseColor * info.attenuation;
- #ifdef SPECULARTERM
- // Specular
- float NdotH = clamp(dot(vNormal, H), 0.000000000001, 1.0);
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, reflectance0, reflectance90, geometricRoughnessFactor);
- result.specular = specTerm * diffuseColor * info.attenuation;
- #endif
- return result;
- }
- lightingInfo computeSpotLighting(spotLightingInfo info, vec3 viewDirectionW, vec3 vNormal, vec4 lightDirection, vec3 diffuseColor, float lightRadius, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, out float NdotL) {
- lightingInfo result;
- // Roughness.
- float lightDistance = sqrt(info.lightDistanceSquared);
- roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
-
- // Diffuse
- vec3 H = normalize(viewDirectionW + info.directionToLightCenterW);
- NdotL = clamp(dot(vNormal, info.directionToLightCenterW), 0.000000000001, 1.0);
- float VdotH = clamp(dot(viewDirectionW, H), 0.0, 1.0);
- float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
- result.diffuse = diffuseTerm * diffuseColor * info.attenuation;
- #ifdef SPECULARTERM
- // Specular
- float NdotH = clamp(dot(vNormal, H), 0.000000000001, 1.0);
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, reflectance0, reflectance90, geometricRoughnessFactor);
- result.specular = specTerm * diffuseColor * info.attenuation;
- #endif
- return result;
- }
- lightingInfo computeDirectionalLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float lightRadius, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, out float NdotL) {
- lightingInfo result;
- float lightDistance = length(-lightData.xyz);
- vec3 lightDirection = normalize(-lightData.xyz);
- // Roughness
- roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
-
- // diffuse
- vec3 H = normalize(viewDirectionW + lightDirection);
- NdotL = clamp(dot(vNormal, lightDirection), 0.00000000001, 1.0);
- float VdotH = clamp(dot(viewDirectionW, H), 0.0, 1.0);
- float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
- result.diffuse = diffuseTerm * diffuseColor;
- #ifdef SPECULARTERM
- // Specular
- float NdotH = clamp(dot(vNormal, H), 0.000000000001, 1.0);
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, reflectance0, reflectance90, geometricRoughnessFactor);
- result.specular = specTerm * diffuseColor;
- #endif
- return result;
- }
- lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, out float NdotL) {
- lightingInfo result;
- // Roughness
- // Do not touch roughness on hemispheric.
- // Diffuse
- NdotL = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
- result.diffuse = mix(groundColor, diffuseColor, NdotL);
- #ifdef SPECULARTERM
- // Specular
- vec3 lightVectorW = normalize(lightData.xyz);
- vec3 H = normalize(viewDirectionW + lightVectorW);
- float NdotH = clamp(dot(vNormal, H), 0.000000000001, 1.0);
- NdotL = clamp(NdotL, 0.000000000001, 1.0);
- float VdotH = clamp(dot(viewDirectionW, H), 0.0, 1.0);
- vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, reflectance0, reflectance90, geometricRoughnessFactor);
- result.specular = specTerm * diffuseColor;
- #endif
- return result;
- }
- vec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler, mat4 textureProjectionMatrix){
- vec4 strq = textureProjectionMatrix * vec4(vPositionW, 1.0);
- strq /= strq.w;
- vec3 textureColor = texture2D(projectionLightSampler, strq.xy).rgb;
- return toLinearSpace(textureColor);
- }
|