Browse Source

Add support for CSM in the inspector

Popov72 5 years ago
parent
commit
1090be6c66

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

@@ -83,6 +83,7 @@
 - Added support for `Material.depthFunction` property ([Popov72](https://github.com/Popov72))
 - Added an optional config option `initialTab` ([ycw](https://github.com/ycw/))
 - Added support for ImportAnimations ([noalak](https://github.com/noalak/))
+- Added support for Cascaded Shadow Maps ([Popov72](https://github.com/Popov72))
 
 ### Tools
 

+ 93 - 20
inspector/src/components/actionTabs/tabs/propertyGrids/lights/commonShadowLightPropertyGridComponent.tsx

@@ -9,8 +9,10 @@ import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { OptionsLineComponent } from '../../../lines/optionsLineComponent';
 import { ShadowGenerator } from 'babylonjs/Lights/Shadows/shadowGenerator';
+import { CascadedShadowGenerator } from 'babylonjs/Lights/Shadows/cascadedShadowGenerator';
 import { SliderLineComponent } from '../../../lines/sliderLineComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { DirectionalLight } from 'babylonjs/Lights/directionalLight';
 
 interface ICommonShadowLightPropertyGridComponentProps {
     globalState: GlobalState;
@@ -20,14 +22,22 @@ interface ICommonShadowLightPropertyGridComponentProps {
 }
 
 export class CommonShadowLightPropertyGridComponent extends React.Component<ICommonShadowLightPropertyGridComponentProps> {
+    private _internals : { generatorType: number, mapSize: number };
+
     constructor(props: ICommonShadowLightPropertyGridComponentProps) {
         super(props);
+
+        this._internals = {
+            generatorType: 0,
+            mapSize: 1024,
+        };
     }
 
     createShadowGenerator() {
         const light = this.props.light;
         const scene = light.getScene();
-        let generator = new ShadowGenerator(512, light);
+        const internals = this._internals;
+        let generator = internals.generatorType === 0 ? new ShadowGenerator(internals.mapSize, light) : new CascadedShadowGenerator(internals.mapSize, light as DirectionalLight);
 
         scene.meshes.forEach((m) => {
             generator.addShadowCaster(m);
@@ -37,45 +47,104 @@ export class CommonShadowLightPropertyGridComponent extends React.Component<ICom
         this.forceUpdate();
     }
 
+    disposeShadowGenerator() {
+        const light = this.props.light;
+
+        light.getShadowGenerator()?.dispose();
+
+        this.forceUpdate();
+    }
+
     render() {
         const light = this.props.light;
-        const generator = light.getShadowGenerator() as ShadowGenerator || null;
-
-        var blurModeOptions = [
-            { label: "None", value: ShadowGenerator.FILTER_NONE },
-            { label: "PCF", value: ShadowGenerator.FILTER_PCF },
-            { label: "PCSS", value: ShadowGenerator.FILTER_PCSS },
-            { label: "Poisson", value: ShadowGenerator.FILTER_POISSONSAMPLING },
-            { label: "Exponential", value: ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP },
-            { label: "Blurred exponential", value: ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP },
-            { label: "Close exponential", value: ShadowGenerator.FILTER_CLOSEEXPONENTIALSHADOWMAP },
-            { label: "Blurred close exponential", value: ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP },
+        const internals = this._internals;
+        const generator = light.getShadowGenerator() as (ShadowGenerator | CascadedShadowGenerator) || null;
+        const csmGenerator = generator instanceof CascadedShadowGenerator;
+        const camera = light.getScene().activeCamera;
+
+        var typeGeneratorOptions = [
+            { label: "Shadow Generator", value: 0 }
         ];
 
+        if (light instanceof DirectionalLight) {
+            typeGeneratorOptions.push({ label: "Cascaded Shadow Generator", value: 1 });
+        }
+
+        var mapSizeOptions = [
+            { label: "2048x2048", value: 2048 },
+            { label: "1024x1024", value: 1024 },
+            { label: "512x512", value: 512 },
+            { label: "256x256", value: 256 },
+        ];
+
+        var blurModeOptions;
+
+        if (generator instanceof CascadedShadowGenerator) {
+            blurModeOptions = [
+                { label: "None", value: ShadowGenerator.FILTER_NONE },
+                { label: "PCF", value: ShadowGenerator.FILTER_PCF },
+                { label: "PCSS", value: ShadowGenerator.FILTER_PCSS },
+            ];
+        } else {
+            blurModeOptions = [
+                { label: "None", value: ShadowGenerator.FILTER_NONE },
+                { label: "PCF", value: ShadowGenerator.FILTER_PCF },
+                { label: "PCSS", value: ShadowGenerator.FILTER_PCSS },
+                { label: "Poisson", value: ShadowGenerator.FILTER_POISSONSAMPLING },
+                { label: "Exponential", value: ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP },
+                { label: "Blurred exponential", value: ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP },
+                { label: "Close exponential", value: ShadowGenerator.FILTER_CLOSEEXPONENTIALSHADOWMAP },
+                { label: "Blurred close exponential", value: ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP },
+            ];
+        }
+
         var filteringQualityOptions = [
             { label: "Low", value: ShadowGenerator.QUALITY_LOW },
             { label: "Medium", value: ShadowGenerator.QUALITY_MEDIUM },
-            { label: "High", value: ShadowGenerator.QUALITY_HIGH }
+            { label: "High", value: ShadowGenerator.QUALITY_HIGH },
         ];
 
+        var numCascadesOptions = [
+            { label: "2", value: 2 },
+            { label: "3", value: 3 },
+            { label: "4", value: 4 },
+        ];
+
+        const near = camera ? camera.minZ : 0, far = camera ? camera.maxZ : 0;
+
         let filter = generator ? generator.filter : 0;
 
         return (
             <div>
                 <LineContainerComponent globalState={this.props.globalState} title="SHADOWS">
                     <CheckBoxLineComponent label="Shadows enabled" target={light} propertyName="shadowEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <FloatLineComponent lockObject={this.props.lockObject} label="Shadows near plane" target={light} propertyName="shadowMinZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <FloatLineComponent lockObject={this.props.lockObject} label="Shadows far plane" target={light} propertyName="shadowMaxZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    { !csmGenerator && <>
+                        <FloatLineComponent lockObject={this.props.lockObject} label="Shadows near plane" target={light} propertyName="shadowMinZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                        <FloatLineComponent lockObject={this.props.lockObject} label="Shadows far plane" target={light} propertyName="shadowMaxZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    </> }
                 </LineContainerComponent>
                 {
                     generator == null &&
                     <LineContainerComponent globalState={this.props.globalState} title="SHADOW GENERATOR">
+                        <OptionsLineComponent label="Type" options={typeGeneratorOptions} target={internals} propertyName="generatorType" />
+                        <OptionsLineComponent label="Map size" options={mapSizeOptions} target={internals} propertyName="mapSize" />
                         <ButtonLineComponent label="Create generator" onClick={() => this.createShadowGenerator()} />
                     </LineContainerComponent>
                 }
                 {
                     generator !== null &&
                     <LineContainerComponent globalState={this.props.globalState} title="SHADOW GENERATOR">
+                        <ButtonLineComponent label="Dispose generator" onClick={() => this.disposeShadowGenerator()} />
+                        { csmGenerator && <>
+                            <OptionsLineComponent label="Num cascades" options={numCascadesOptions} target={generator} propertyName="numCascades" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <CheckBoxLineComponent label="Debug mode" target={generator} propertyName="debug" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <CheckBoxLineComponent label="Stabilize cascades" target={generator} propertyName="stabilizeCascades" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <SliderLineComponent label="Lambda" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="lambda" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <SliderLineComponent label="Cascade blend" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="cascadeBlendPercentage" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <CheckBoxLineComponent label="Depth clamp" target={generator} propertyName="depthClamp" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <CheckBoxLineComponent label="Auto-Calc depth bounds" target={generator} propertyName="autoCalcDepthBounds" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <SliderLineComponent label="Shadow MaxZ" minimum={near} maximum={far} step={0.5} target={generator} propertyName="shadowMaxZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                        </> }
                         <FloatLineComponent lockObject={this.props.lockObject} digits={4} step="0.0001" label="Bias" target={generator} propertyName="bias" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <FloatLineComponent lockObject={this.props.lockObject} label="Normal bias" target={generator} propertyName="normalBias" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         <SliderLineComponent label="Darkness" target={generator} minimum={0} maximum={1} step={0.01} propertyName="darkness" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -98,28 +167,32 @@ export class CommonShadowLightPropertyGridComponent extends React.Component<ICom
                             <SliderLineComponent label="Penumbra ratio" minimum={0} maximum={0.5} step={0.001} target={generator} propertyName="contactHardeningLightSizeUVRatio" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         }
                         {
-                            (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
+                            !csmGenerator && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
                             <CheckBoxLineComponent label="Use kernel blur" target={generator} propertyName="useKernelBlur"
                                 onValueChanged={() => this.forceUpdate()}
                                 onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         }
                         {
-                            (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
+                            (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
                             !generator.useKernelBlur &&
                             <SliderLineComponent label="Blur box offset" target={generator} propertyName="blurBoxOffset" minimum={1} maximum={64} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />}
                         {
-                            (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
+                            (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_BLURCLOSEEXPONENTIALSHADOWMAP) &&
                             generator.useKernelBlur &&
                             <SliderLineComponent label="Blur kernel" target={generator} propertyName="blurKernel" minimum={1} maximum={64} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         }
                         {
-                            (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
+                            (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
                             <FloatLineComponent lockObject={this.props.lockObject} label="Depth scale" target={generator} propertyName="depthScale" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         }
                         {
-                            (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
+                            (generator instanceof ShadowGenerator) && (filter === ShadowGenerator.FILTER_BLUREXPONENTIALSHADOWMAP || filter === ShadowGenerator.FILTER_EXPONENTIALSHADOWMAP) &&
                             <SliderLineComponent label="Blur scale" target={generator} propertyName="blurScale" minimum={1} maximum={4} step={1} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                         }
+                        {
+                            csmGenerator && (filter === ShadowGenerator.FILTER_PCSS) &&
+                            <SliderLineComponent label="Penumbra darkness" minimum={0} maximum={1.0} step={0.01} target={generator} propertyName="penumbraDarkness" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                        }
                     </LineContainerComponent>
                 }
             </div>

+ 10 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/lights/directionalLightPropertyGridComponent.tsx

@@ -9,6 +9,9 @@ import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
 import { CommonShadowLightPropertyGridComponent } from "./commonShadowLightPropertyGridComponent";
 import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
+import { CheckBoxLineComponent } from '../../../lines/checkBoxLineComponent';
+import { ShadowGenerator } from 'babylonjs/Lights/Shadows/shadowGenerator';
+import { CascadedShadowGenerator } from 'babylonjs/Lights/Shadows/cascadedShadowGenerator';
 
 interface IDirectionalLightPropertyGridComponentProps {
     globalState: GlobalState,
@@ -25,6 +28,10 @@ export class DirectionalLightPropertyGridComponent extends React.Component<IDire
     render() {
         const light = this.props.light;
 
+        const generator = light.getShadowGenerator() as (ShadowGenerator | CascadedShadowGenerator) || null;
+
+        const hideAutoCalcShadowZBounds = generator instanceof CascadedShadowGenerator;
+
         return (
             <div className="pane">
                 <CommonLightPropertyGridComponent globalState={this.props.globalState} lockObject={this.props.lockObject} light={light} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -33,6 +40,9 @@ export class DirectionalLightPropertyGridComponent extends React.Component<IDire
                     <Color3LineComponent label="Specular" target={light} propertyName="specular" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <Vector3LineComponent label="Position" target={light} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <Vector3LineComponent label="Direction" target={light} propertyName="direction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    { !hideAutoCalcShadowZBounds &&
+                        <CheckBoxLineComponent label="Auto Calc Shadow ZBounds" target={light} propertyName="autoCalcShadowZBounds" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    }
                 </LineContainerComponent>
                 <CommonShadowLightPropertyGridComponent globalState={this.props.globalState} lockObject={this.props.lockObject} light={light} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
             </div>