瀏覽代碼

Merge branch 'master' into MSFT_audio_emitter.only

Jamie Marconi 7 年之前
父節點
當前提交
584312ae16

+ 2 - 5
Playground/index-local.html

@@ -447,6 +447,7 @@
         <script src="js/pbt.js"></script>
         <script>
             BABYLONDEVTOOLS.Loader
+                .require('node_modules/monaco-editor/min/vs/loader.js')
                 .require('js/index.js')
                 .load(function () {
                     BABYLON.DracoCompression.Configuration.decoder = {
@@ -454,12 +455,8 @@
                         wasmBinaryUrl: "../dist/preview%20release/draco_decoder_gltf.wasm",
                         fallbackUrl: "../dist/preview%20release/draco_decoder_gltf.js"
                     };
-                    var script = document.createElement('script');
-                    script.type = 'text/javascript';
-                    script.src = "node_modules/monaco-editor/min/vs/loader.js";
-                    document.head.appendChild(script);
                 });
         </script>
     </body>
 
-</html>
+</html>

+ 1 - 0
dist/preview release/what's new.md

@@ -81,6 +81,7 @@
 - Gizmo manager's internal gizmos are now public ([TrevorDev](https://github.com/TrevorDev))
 - Ability to customize meshes on gizmos ([TrevorDev](https://github.com/TrevorDev))
 - Added gltf light falloff [Issue 4148](https://github.com/BabylonJS/Babylon.js/issues/4148) ([sebavan](http://www.github.com/sebavan))
+- Added falloff type per light to prevent material only inconsistencies [Issue 4148](https://github.com/BabylonJS/Babylon.js/issues/4148) ([sebavan](http://www.github.com/sebavan))
 - Added WeightedSound; selects one from many Sounds with random weight for playback. ([najadojo](https://github.com/najadojo))
 
 ### glTF Loader

+ 4 - 4
src/Cameras/babylon.targetCamera.ts

@@ -150,6 +150,10 @@
         public setTarget(target: Vector3): void {
             this.upVector.normalize();
 
+            if (this.position.z === target.z) {
+                this.position.z += Epsilon;
+            }
+
             Matrix.LookAtLHToRef(this.position, target, this.upVector, this._camMatrix);
             this._camMatrix.invert();
 
@@ -303,10 +307,6 @@
                 Vector3.TransformNormalToRef(up, parentWorldMatrix, this._globalCurrentUpVector);
                 this._markSyncedWithParent();
             } else {
-                if (Scalar.WithinEpsilon(position.y, target.y, BABYLON.Epsilon) && Scalar.WithinEpsilon(position.z, target.z, BABYLON.Epsilon)) {
-                    position.z += BABYLON.Epsilon;
-                }
-
                 this._globalPosition.copyFrom(position);
                 this._globalCurrentTarget.copyFrom(target);
                 this._globalCurrentUpVector.copyFrom(up);

+ 34 - 0
src/Lights/babylon.light.ts

@@ -6,6 +6,29 @@ module BABYLON {
      */
     export abstract class Light extends Node {
 
+        /**
+         * Falloff Default: light is falling off following the material specification: 
+         * standard material is using standard falloff whereas pbr material can request special falloff per materials.
+         */
+        public static readonly FALLOFF_DEFAULT = 0;
+
+        /**
+         * Falloff Physical: light is falling off following the inverse squared distance law.
+         */
+        public static readonly FALLOFF_PHYSICAL = 1;
+
+        /**
+         * Falloff gltf: light is falling off as described in the gltf moving to PBR document 
+         * to enhance interoperability with other engines.
+         */
+        public static readonly FALLOFF_GLTF = 2;
+
+        /**
+         * Falloff Standard: light is falling off like in the standard material 
+         * to enhance interoperability with other materials.
+         */
+        public static readonly FALLOFF_STANDARD = 3;
+
         //lightmapMode Consts
         /**
          * If every light affecting the material is in this lightmapMode,
@@ -83,6 +106,17 @@ module BABYLON {
         public specular = new Color3(1.0, 1.0, 1.0);
 
         /**
+         * Defines the falloff type for this light. This lets overrriding how punctual light are 
+         * falling off base on range or angle.
+         * This can be set to any values in Light.FALLOFF_x.
+         * 
+         * Note: This is only usefull for PBR Materials at the moment. This could be extended if required to 
+         * other types of materials.
+         */
+        @serialize()
+        public falloffType = Light.FALLOFF_DEFAULT;
+
+        /**
          * Strength of the light.
          * Note: By default it is define in the framework own unit.
          * Note: In PBR materials the intensityMode can be use to chose what unit the intensity is defined in.

+ 17 - 0
src/Materials/babylon.materialHelper.ts

@@ -218,6 +218,23 @@ module BABYLON {
 
                     light.prepareLightSpecificDefines(defines, lightIndex);
 
+                    // FallOff.
+                    defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = false;
+                    defines["LIGHT_FALLOFF_GLTF" + lightIndex] = false;
+                    defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = false;
+
+                    switch (light.falloffType) {
+                        case Light.FALLOFF_GLTF:
+                        defines["LIGHT_FALLOFF_GLTF" + lightIndex] = true;
+                        break;
+                        case Light.FALLOFF_PHYSICAL:
+                        defines["LIGHT_FALLOFF_PHYSICAL" + lightIndex] = true;
+                        break;
+                        case Light.FALLOFF_STANDARD:
+                        defines["LIGHT_FALLOFF_STANDARD" + lightIndex] = true;
+                        break;
+                    }
+
                     // Specular
                     if (specularSupported && !light.specular.equalsFloats(0, 0, 0)) {
                         specularEnabled = true;

+ 31 - 3
src/Shaders/ShadersInclude/lightFragment.fx

@@ -4,11 +4,39 @@
     #else
         #ifdef PBR
             #ifdef SPOTLIGHT{X}
-                info = computeSpotLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDirection, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, light{X}.vLightFalloff, NdotL);
+                spotInfo = computeSpotLightingInfo(light{X}.vLightData);
+
+                #ifdef LIGHT_FALLOFF_GLTF{X}
+                    spotInfo.attenuation = computeDistanceLightFalloff_GLTF(spotInfo.lightDistanceSquared, light{X}.vLightFalloff.y);
+                    spotInfo.attenuation *= computeDirectionalLightFalloff_GLTF(light{X}.vLightDirection.xyz, spotInfo.directionToLightCenterW, light{X}.vLightFalloff.z, light{X}.vLightFalloff.w);
+                #elif defined(LIGHT_FALLOFF_PHYSICAL{X})
+                    spotInfo.attenuation = computeDistanceLightFalloff_Physical(spotInfo.lightDistanceSquared);
+                    spotInfo.attenuation *= computeDirectionalLightFalloff_Physical(light{X}.vLightDirection.xyz, spotInfo.directionToLightCenterW, light{X}.vLightDirection.w);
+                #elif defined(LIGHT_FALLOFF_STANDARD{X})
+                    spotInfo.attenuation = computeDistanceLightFalloff_Standard(spotInfo.lightOffset, light{X}.vLightFalloff.x);
+                    spotInfo.attenuation *= computeDirectionalLightFalloff_Standard(light{X}.vLightDirection.xyz, spotInfo.directionToLightCenterW, light{X}.vLightDirection.w, light{X}.vLightData.w);
+                #else
+                    spotInfo.attenuation = computeDistanceLightFalloff(spotInfo.lightOffset, spotInfo.lightDistanceSquared, light{X}.vLightFalloff.x, light{X}.vLightFalloff.y);
+                    spotInfo.attenuation *= computeDirectionalLightFalloff(light{X}.vLightDirection.xyz, spotInfo.directionToLightCenterW, light{X}.vLightDirection.w, light{X}.vLightData.w, light{X}.vLightFalloff.z, light{X}.vLightFalloff.w);
+                #endif
+
+                info = computeSpotLighting(spotInfo, viewDirectionW, normalW, light{X}.vLightDirection, light{X}.vLightDiffuse.rgb, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, NdotL);
+            #elif defined(POINTLIGHT{X})
+                pointInfo = computePointLightingInfo(light{X}.vLightData);
+
+                #ifdef LIGHT_FALLOFF_GLTF{X}
+                    pointInfo.attenuation = computeDistanceLightFalloff_GLTF(pointInfo.lightDistanceSquared, light{X}.vLightFalloff.y);
+                #elif defined(LIGHT_FALLOFF_PHYSICAL{X})
+                    pointInfo.attenuation = computeDistanceLightFalloff_Physical(pointInfo.lightDistanceSquared);
+                #elif defined(LIGHT_FALLOFF_STANDARD{X})
+                    pointInfo.attenuation = computeDistanceLightFalloff_Standard(pointInfo.lightOffset, light{X}.vLightFalloff.x);
+                #else
+                    pointInfo.attenuation = computeDistanceLightFalloff(pointInfo.lightOffset, pointInfo.lightDistanceSquared, light{X}.vLightFalloff.x, light{X}.vLightFalloff.y);
+                #endif
+                
+                info = computePointLighting(pointInfo, viewDirectionW, normalW, light{X}.vLightDiffuse.rgb, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, NdotL);
             #elif defined(HEMILIGHT{X})
                 info = computeHemisphericLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightGround, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, NdotL);
-            #elif defined(POINTLIGHT{X})
-                info = computePointLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, light{X}.vLightFalloff, NdotL);
             #elif defined(DIRLIGHT{X})
                 info = computeDirectionalLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR0, specularEnvironmentR90, geometricRoughnessFactor, NdotL);
             #endif

+ 133 - 81
src/Shaders/ShadersInclude/pbrLightFunctions.fx

@@ -7,72 +7,139 @@ struct lightingInfo
     #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
-        float lightDistanceFalloff = 1.0 / ((lightDistanceSquared + 0.001));
+        return computeDistanceLightFalloff_Physical(lightDistanceSquared);
     #elif defined(USEGLTFLIGHTFALLOFF)
-        // Prevents infinity issues at 0.
-        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 computeDistanceLightFalloff_GLTF(lightDistanceSquared, inverseSquaredRange);
     #else
-        float lightDistanceFalloff = max(0., 1.0 - length(lightOffset) / range);
+        return computeDistanceLightFalloff_Standard(lightOffset, range);
     #endif
-    
-    return lightDistanceFalloff;
 }
 
-float computeDirectionalLightFalloff(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle, float exponent, float lightAngleScale, float lightAngleOffset)
+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
-        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);
-        falloff = exp2(dot(vec4(directionToLightCenterW, 1.0), lightDirectionSpreadSG));
+        return computeDirectionalLightFalloff_Physical(lightDirection, directionToLightCenterW, cosHalfAngle);
     #elif defined(USEGLTFLIGHTFALLOFF)
-        // On the CPU
-        // float lightAngleScale = 1.0 f / max (0.001f, ( cosInner - cosOuter ));
-        // float lightAngleOffset = -cosOuter * angleScale;
-
-        float cd = dot(-lightDirection, directionToLightCenterW);
-        falloff = clamp(cd * lightAngleScale + lightAngleOffset, 0., 1.);
-        // smooth the transition
-        falloff *= falloff;
+        return computeDirectionalLightFalloff_GLTF(lightDirection, directionToLightCenterW, lightAngleScale, lightAngleOffset);
     #else
-        float cosAngle = max(0.000000000000001, dot(-lightDirection, directionToLightCenterW));
-        if (cosAngle >= cosHalfAngle)
-        {
-            falloff = max(0., pow(cosAngle, exponent));
-        }
+        return computeDirectionalLightFalloff_Standard(lightDirection, directionToLightCenterW, cosHalfAngle, exponent);
     #endif
-    
-    return falloff;
 }
 
-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;
+pointLightingInfo computePointLightingInfo(vec4 lightData) {
+    pointLightingInfo result;
 
-    float lightDistance = length(-lightData.xyz);
-    vec3 lightDirection = normalize(-lightData.xyz);
+    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);
     
@@ -82,83 +149,68 @@ lightingInfo computeDirectionalLighting(vec3 viewDirectionW, vec3 vNormal, vec4
     float VdotH = clamp(dot(viewDirectionW, H), 0.0, 1.0);
 
     float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
-    result.diffuse = diffuseTerm * diffuseColor;
+    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;
+        result.specular = specTerm * diffuseColor * info.attenuation;
     #endif
 
     return result;
 }
 
-lightingInfo computePointLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float lightRadius, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec4 lightFalloff, out float NdotL) {
+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;
 
-    vec3 lightOffset = lightData.xyz - vPositionW;
-    float lightDistanceSquared = dot(lightOffset, lightOffset);
-    float attenuation = computeDistanceLightFalloff(lightOffset, lightDistanceSquared, lightFalloff.x, lightFalloff.y);
-    
-    float lightDistance = sqrt(lightDistanceSquared);
-    vec3 lightDirection = normalize(lightOffset);
-    
-    // Roughness
+    // Roughness.
+    float lightDistance = sqrt(info.lightDistanceSquared);
     roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
     
-    // diffuse
-    vec3 H = normalize(viewDirectionW + lightDirection);
-    NdotL = clamp(dot(vNormal, lightDirection), 0.00000000001, 1.0);
+    // 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 * attenuation;
+    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 * attenuation;
+        result.specular = specTerm * diffuseColor * info.attenuation;
     #endif
 
     return result;
 }
 
-lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float lightRadius, float roughness, float NdotV, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec4 lightFalloff, out float NdotL) {
+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;
 
-    vec3 lightOffset = lightData.xyz - vPositionW;
-    vec3 directionToLightCenterW = normalize(lightOffset);
+    float lightDistance = length(-lightData.xyz);
+    vec3 lightDirection = normalize(-lightData.xyz);
 
-    // Distance falloff.
-    float lightDistanceSquared = dot(lightOffset, lightOffset);
-    float attenuation = computeDistanceLightFalloff(lightOffset, lightDistanceSquared, lightFalloff.x, lightFalloff.y);
-    
-    // Directional falloff.
-    float directionalAttenuation = computeDirectionalLightFalloff(lightDirection.xyz, directionToLightCenterW, lightDirection.w, lightData.w, lightFalloff.z, lightFalloff.w);
-    attenuation *= directionalAttenuation;
-    
-    // Roughness.
-    float lightDistance = sqrt(lightDistanceSquared);
+    // Roughness
     roughness = adjustRoughnessFromLightProperties(roughness, lightRadius, lightDistance);
     
-    // Diffuse
-    vec3 H = normalize(viewDirectionW + directionToLightCenterW);
-    NdotL = clamp(dot(vNormal, directionToLightCenterW), 0.000000000001, 1.0);
+    // 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 * attenuation;
+    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 * attenuation;
+        result.specular = specTerm * diffuseColor;
     #endif
 
     return result;

+ 5 - 0
src/Shaders/pbr.fragment.fx

@@ -639,6 +639,11 @@ void main(void) {
     #endif
 
         lightingInfo info;
+
+        pointLightingInfo pointInfo;
+
+        spotLightingInfo spotInfo;
+
         float shadow = 1.; // 1 - shadowLevel
         float NdotL = -1.;
 

二進制
tests/validation/ReferenceImages/lightFalloff.png


+ 5 - 0
tests/validation/config.json

@@ -502,6 +502,11 @@
       "title": "DDS",
       "playgroundId": "#ZI77S7#3",
       "referenceImage": "dds.png"
+    },
+    {
+      "title": "LightFalloff",
+      "playgroundId": "#20OAV9#201",
+      "referenceImage": "lightFalloff.png"
     }
   ]
 }