浏览代码

Fix bug with CSM and autoCalcDepthBounds = true

Popov72 5 年之前
父节点
当前提交
4623c25cb2
共有 2 个文件被更改,包括 35 次插入2 次删除
  1. 1 0
      dist/preview release/what's new.md
  2. 34 2
      materialsLibrary/src/shadowOnly/shadowOnlyMaterial.ts

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

@@ -191,6 +191,7 @@
 - Make sure bone matrices are up to date when calling `TransformNode.attachToBone` ([Popov72](https://github.com/Popov72))
 - Fix display problem with transparent objects and SSAO2 pipeline (bug in the `GeometryBufferRenderer`) ([Popov72](https://github.com/Popov72))
 - Fixed `Sound` not accepting a `TransformNode` as a source for spatial sound ([Poolminer](https://github.com/Poolminer))
+- Fix bug when using `ShadowOnlyMaterial` with Cascaded Shadow Map and `autoCalcDepthBounds` is `true` ([Popov72](https://github.com/Popov72))
 
 ## Breaking changes
 

+ 34 - 2
materialsLibrary/src/shadowOnly/shadowOnlyMaterial.ts

@@ -18,6 +18,7 @@ import { _TypeStore } from 'babylonjs/Misc/typeStore';
 import "./shadowOnly.fragment";
 import "./shadowOnly.vertex";
 import { EffectFallbacks } from 'babylonjs/Materials/effectFallbacks';
+import { CascadedShadowGenerator } from 'babylonjs/Lights/Shadows/cascadedShadowGenerator';
 
 class ShadowOnlyMaterialDefines extends MaterialDefines {
     public CLIPPLANE = false;
@@ -41,6 +42,7 @@ class ShadowOnlyMaterialDefines extends MaterialDefines {
 
 export class ShadowOnlyMaterial extends PushMaterial {
     private _activeLight: IShadowLight;
+    private _needAlphaBlending = true;
 
     constructor(name: string, scene: Scene) {
         super(name, scene);
@@ -49,7 +51,7 @@ export class ShadowOnlyMaterial extends PushMaterial {
     public shadowColor = Color3.Black();
 
     public needAlphaBlending(): boolean {
-        return true;
+        return this._needAlphaBlending;
     }
 
     public needAlphaTesting(): boolean {
@@ -68,6 +70,15 @@ export class ShadowOnlyMaterial extends PushMaterial {
         this._activeLight = light;
     }
 
+    private _getFirstShadowLightForMesh(mesh: AbstractMesh): Nullable<IShadowLight> {
+        for (var light of mesh.lightSources) {
+            if (light.shadowEnabled) {
+                return light as IShadowLight;
+            }
+        }
+        return null;
+    }
+
     // Methods
     public isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean {
         if (this.isFrozen) {
@@ -114,6 +125,16 @@ export class ShadowOnlyMaterial extends PushMaterial {
 
         defines._needNormals = MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, false, 1);
 
+        const shadowGenerator = this._getFirstShadowLightForMesh(mesh)?.getShadowGenerator();
+
+        this._needAlphaBlending = true;
+
+        if (shadowGenerator && (shadowGenerator as any).getClassName && (shadowGenerator as any).getClassName() === 'CascadedShadowGenerator') {
+            const csg = shadowGenerator as CascadedShadowGenerator;
+
+            this._needAlphaBlending = !csg.autoCalcDepthBounds;
+        }
+
         // Attribs
         MaterialHelper.PrepareDefinesForAttributes(mesh, defines, false, true);
 
@@ -226,10 +247,21 @@ export class ShadowOnlyMaterial extends PushMaterial {
         // Lights
         if (scene.lightsEnabled) {
             MaterialHelper.BindLights(scene, mesh, this._activeEffect, defines, 1);
+
+            const light = this._getFirstShadowLightForMesh(mesh);
+
+            if (light) {
+                // Make sure the uniforms for this light will be rebound for other materials using this light when rendering the current frame.
+                // Indeed, there is an optimization in Light that binds the light uniforms only once per frame for a given light (if using ubo).
+                // Doing this way assumes that all uses of this light are the same, meaning all parameters passed to Light._bindLlight
+                // are the same, notably useSpecular. However, isReadyForSubMesh (see above) is passing false for this parameter, which may not be
+                // the value the other materials may pass.
+                light._renderId = -1;
+            }
         }
 
         // View
-        if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+        if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE || defines["SHADOWCSM0"]) {
             this._activeEffect.setMatrix("view", scene.getViewMatrix());
         }