Benjamin Guignabert 5 年之前
父節點
當前提交
361635b406

+ 3 - 7
src/Materials/PBR/pbrSubSurfaceConfiguration.ts

@@ -43,16 +43,12 @@ export interface IMaterialSubSurfaceDefines {
     _areTexturesDirty: boolean;
 }
 
-export enum SubsurfaceDiffusionProfile {
-    NEUTRAL = 0,
-    SKIN = 1,
-    FOLIAGE = 2,
-};
 
 /**
  * Define the code related to the sub surface parameters of the pbr material.
  */
 export class PBRSubSurfaceConfiguration {
+
     private _isRefractionEnabled = false;
     /**
      * Defines if the refraction is enabled in the material.
@@ -81,7 +77,7 @@ export class PBRSubSurfaceConfiguration {
      * Diffusion profile for subsurface scattering.
      * Useful for better scattering in the skins or foliages.
      */
-    public scatteringDiffusionProfile = SubsurfaceDiffusionProfile.NEUTRAL;
+    public scatteringDiffusionProfileIndex = 0;
 
     /**
      * Defines the refraction intensity of the material.
@@ -383,7 +379,7 @@ export class PBRSubSurfaceConfiguration {
 
 
             if (this.isScatteringEnabled) {
-                uniformBuffer.updateFloat("scatteringDiffusionProfile", this.scatteringDiffusionProfile);
+                uniformBuffer.updateFloat("scatteringDiffusionProfile", this.scatteringDiffusionProfileIndex);
             }
             uniformBuffer.updateColor3("vDiffusionDistance", this.diffusionDistance);
 

+ 35 - 2
src/PostProcesses/SubSurfaceScatteringPostProcess.ts

@@ -7,6 +7,7 @@ import { Engine } from "../Engines/engine";
 import { Scene } from "../scene";
 import { Color3 } from "../Maths/math.color";
 import { Constants } from "../Engines/constants";
+import { Logger } from "../Misc/logger";
 
 import "../Shaders/sceneCompositor.fragment";
 import "../Shaders/postprocess.vertex";
@@ -20,24 +21,33 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
     /** @hidden */
     public texelHeight: number;
 
+    private _diffusionS: number[] = [];
+    private _filterRadii: number[] = [];
+    private _diffusionD: number[] = [];
+
     constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT) {
-        super(name, "subSurfaceScattering", ["texelSize", "viewportSize", "metersPerUnit"], ["inputSampler", "irradianceSampler", "depthSampler", "albedoSampler"], options, camera, samplingMode || Texture.BILINEAR_SAMPLINGMODE, engine, reusable, null, textureType, "postprocess", undefined, true);
+        super(name, "subSurfaceScattering", ["texelSize", "viewportSize", "metersPerUnit"], ["diffusionS", "diffusionD", "filterRadii", "irradianceSampler", "depthSampler", "albedoSampler"], options, camera, samplingMode || Texture.BILINEAR_SAMPLINGMODE, engine, reusable, null, textureType, "postprocess", undefined, true);
         this._scene = scene;
 
         const defines = this._getDefines();
         this.updateEffect(defines);
 
+        // Adding default diffusion profile
+        this.addDiffusionProfile(new Color3(1, 1, 1));
+
         this.onApplyObservable.add((effect: Effect) => {
             var texelSize = this.texelSize;
             effect.setFloat("metersPerUnit", scene.metersPerUnit);
             effect.setFloat2("texelSize", texelSize.x, texelSize.y);
-            effect.setTexture("inputSampler", scene.highDefinitionMRT.textures[4]);
             effect.setTexture("irradianceSampler", scene.highDefinitionMRT.textures[1]);
             effect.setTexture("depthSampler", scene.highDefinitionMRT.textures[2]);
             effect.setTexture("albedoSampler", scene.highDefinitionMRT.textures[3]);
             effect.setFloat2("viewportSize",
                 Math.tan(scene.activeCamera!.fov / 2) * scene.getEngine().getAspectRatio(scene.activeCamera!, true),
                 Math.tan(scene.activeCamera!.fov / 2));
+            effect.setArray3("diffusionS", this._diffusionS);
+            effect.setArray("diffusionD", this._diffusionD);
+            effect.setArray("filterRadii", this._filterRadii);
         });
 
     }
@@ -58,6 +68,29 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
         return defines;
     }
 
+    public addDiffusionProfile(color: Color3) : number {
+        if (this._diffusionD.length >= 5) {
+            // We only suppport 5 diffusion profiles
+            Logger.Error("You already reached the maximum number of diffusion profiles.");
+            return -1;
+        }
+
+        // Do not add doubles
+        for (let i = 0; i < this._diffusionS.length / 3; i++) {
+            if (this._diffusionS[i * 3] === color.r && 
+                this._diffusionS[i * 3 + 1] === color.g && 
+                this._diffusionS[i * 3 + 2] === color.b) {
+                return i;
+            }
+        }
+
+        this._diffusionS.push(color.r, color.b, color.g);
+        this._diffusionD.push(Math.max(Math.max(color.r, color.b), color.g));
+        this._filterRadii.push(this.getDiffusionProfileParameters(color));
+
+        return this._diffusionD.length - 1;
+    }
+
     public getDiffusionProfileParameters(color: Color3)
     {
         const cdf = 0.997;

+ 3 - 2
src/PostProcesses/postProcessManager.ts

@@ -102,8 +102,9 @@ export class PostProcessManager {
      * @param forceFullscreenViewport force gl.viewport to be full screen eg. 0,0,textureWidth,textureHeight
      * @param faceIndex defines the face to render to if a cubemap is defined as the target
      * @param lodLevel defines which lod of the texture to render to
+     * @param doNotBindFrambuffer If set to true, assumes that the framebuffer has been bound previously
      */
-    public directRender(postProcesses: PostProcess[], targetTexture: Nullable<InternalTexture> = null, forceFullscreenViewport = false, faceIndex = 0, lodLevel = 0): void {
+    public directRender(postProcesses: PostProcess[], targetTexture: Nullable<InternalTexture> = null, forceFullscreenViewport = false, faceIndex = 0, lodLevel = 0, doNotBindFrambuffer = false): void {
         var engine = this._scene.getEngine();
 
         for (var index = 0; index < postProcesses.length; index++) {
@@ -112,7 +113,7 @@ export class PostProcessManager {
             } else {
                 if (targetTexture) {
                     engine.bindFramebuffer(targetTexture, faceIndex, undefined, undefined, forceFullscreenViewport, lodLevel);
-                } else {
+                } else if (!doNotBindFrambuffer) {
                     engine.restoreDefaultFramebuffer();
                 }
             }

+ 30 - 37
src/Rendering/deferredSceneComponent.ts

@@ -1,78 +1,75 @@
 import { Nullable } from "../types";
 import { Scene } from "../scene";
 import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
-import { SmartArrayNoDuplicate } from "../Misc/smartArray";
-import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
-import { GeometryBufferRenderer } from "./geometryBufferRenderer";
+import { PrePassRenderer } from "./prePassRenderer";
 
 declare module "../scene" {
     export interface Scene {
         /** @hidden (Backing field) */
-        _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
+        _prePassRenderer: Nullable<PrePassRenderer>;
 
         /**
          * Gets or Sets the current geometry buffer associated to the scene.
          */
-        geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
+        prePassRenderer: Nullable<PrePassRenderer>;
 
         /**
-         * Enables a GeometryBufferRender and associates it with the scene
-         * @param ratio defines the scaling ratio to apply to the renderer (1 by default which means same resolution)
-         * @returns the GeometryBufferRenderer
+         * Enables the prepass and associates it with the scene
+         * @returns the PrePassRenderer
          */
-        enableGeometryBufferRenderer(ratio?: number): Nullable<GeometryBufferRenderer>;
+        enablePrepassRenderer(ratio?: number): Nullable<PrePassRenderer>;
 
         /**
-         * Disables the GeometryBufferRender associated with the scene
+         * Disables the prepass associated with the scene
          */
-        disableGeometryBufferRenderer(): void;
+        disablePrepassRenderer(): void;
     }
 }
 
-Object.defineProperty(Scene.prototype, "geometryBufferRenderer", {
+Object.defineProperty(Scene.prototype, "PrePassRenderer", {
     get: function(this: Scene) {
-        this._geometryBufferRenderer;
+        this._prePassRenderer;
     },
-    set: function(this: Scene, value: Nullable<GeometryBufferRenderer>) {
+    set: function(this: Scene, value: Nullable<PrePassRenderer>) {
         if (value && value.isSupported) {
-            this._geometryBufferRenderer = value;
+            this._prePassRenderer = value;
         }
     },
     enumerable: true,
     configurable: true
 });
 
-Scene.prototype.enableGeometryBufferRenderer = function(ratio: number = 1): Nullable<GeometryBufferRenderer> {
-    if (this._geometryBufferRenderer) {
-        return this._geometryBufferRenderer;
+Scene.prototype.enablePrepassRenderer = function(ratio: number = 1): Nullable<PrePassRenderer> {
+    if (this._prePassRenderer) {
+        return this._prePassRenderer;
     }
 
-    this._geometryBufferRenderer = new GeometryBufferRenderer(this, ratio);
-    if (!this._geometryBufferRenderer.isSupported) {
-        this._geometryBufferRenderer = null;
+    this._prePassRenderer = new PrePassRenderer(this);
+    if (!this._prePassRenderer.isSupported) {
+        this._prePassRenderer = null;
     }
 
-    return this._geometryBufferRenderer;
+    return this._prePassRenderer;
 };
 
-Scene.prototype.disableGeometryBufferRenderer = function(): void {
-    if (!this._geometryBufferRenderer) {
+Scene.prototype.disablePrepassRenderer = function(): void {
+    if (!this._prePassRenderer) {
         return;
     }
 
-    this._geometryBufferRenderer.dispose();
-    this._geometryBufferRenderer = null;
+    this._prePassRenderer.dispose();
+    this._prePassRenderer = null;
 };
 
 /**
  * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
  * in several rendering techniques.
  */
-export class GeometryBufferRendererSceneComponent implements ISceneComponent {
+export class PrePassSceneComponent implements ISceneComponent {
     /**
      * The component name helpful to identify the component in the list of scene components.
      */
-    public readonly name = SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER;
+    public readonly name = SceneComponentConstants.NAME_PREPASSRENDERER;
 
     /**
      * The scene the component belongs to.
@@ -91,7 +88,8 @@ export class GeometryBufferRendererSceneComponent implements ISceneComponent {
      * Registers the component in a given scene
      */
     public register(): void {
-        this.scene._gatherRenderTargetsStage.registerStep(SceneComponentConstants.STEP_GATHERRENDERTARGETS_GEOMETRYBUFFERRENDERER, this, this._gatherRenderTargets);
+        this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this.scene._prePassRenderer._beforeCameraDraw);
+        this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this.scene._prePassRenderer._afterCameraDraw);
     }
 
     /**
@@ -109,18 +107,13 @@ export class GeometryBufferRendererSceneComponent implements ISceneComponent {
         // Nothing to do for this component
     }
 
-    private _gatherRenderTargets(renderTargets: SmartArrayNoDuplicate<RenderTargetTexture>): void {
-        if (this.scene._geometryBufferRenderer) {
-            renderTargets.push(this.scene._geometryBufferRenderer.getGBuffer());
-        }
-    }
 }
 
-GeometryBufferRenderer._SceneComponentInitialization = (scene: Scene) => {
+PrePassRenderer._SceneComponentInitialization = (scene: Scene) => {
     // Register the G Buffer component to the scene.
-    let component = scene._getComponent(SceneComponentConstants.NAME_GEOMETRYBUFFERRENDERER) as GeometryBufferRendererSceneComponent;
+    let component = scene._getComponent(SceneComponentConstants.NAME_PREPASSRENDERER) as PrePassSceneComponent;
     if (!component) {
-        component = new GeometryBufferRendererSceneComponent(scene);
+        component = new PrePassSceneComponent(scene);
         scene._addComponent(component);
     }
 };

+ 15 - 11
src/Shaders/ShadersInclude/diffusionProfile.fx

@@ -1,12 +1,16 @@
-struct DiffusionProfile
-{
-  vec3 S;
-  float d;
-  float filterRadius;
-};
+uniform vec3 diffusionS[5];
+uniform float diffusionD[5];
+uniform float filterRadii[5];
 
-DiffusionProfile diffusionProfiles[3] = DiffusionProfile[3](
-	DiffusionProfile(vec3(1., 1., 1.), 1., 16.564398753373407), // neutral
-	DiffusionProfile(vec3(0.7568628, 0.32156864, 0.20000002), 0.7568628, 12.536977220794705), // skin
-	DiffusionProfile(vec3(0.7568628, 0.7019608, 0.24313727), 0.7568628, 12.536977220794705) // foliage
-);
+// struct DiffusionProfile
+// {
+//   vec3 S;
+//   float d;
+//   float filterRadius;
+// };
+
+// DiffusionProfile diffusionProfiles[3] = DiffusionProfile[3](
+// 	DiffusionProfile(vec3(1., 1., 1.), 1., 16.564398753373407), // neutral
+// 	DiffusionProfile(vec3(0.7568628, 0.32156864, 0.20000002), 0.7568628, 12.536977220794705), // skin
+// 	DiffusionProfile(vec3(0.7568628, 0.7019608, 0.24313727), 0.7568628, 12.536977220794705) // foliage
+// );

+ 4 - 4
src/Shaders/subSurfaceScattering.fragment.fx

@@ -160,10 +160,10 @@ void main(void)
         return;
     }
 
-	float  distScale     = 1.; //sssData.subsurfaceMask;
-	vec3 S             = diffusionProfiles[diffusionProfileIndex].S;
-	float  d             = diffusionProfiles[diffusionProfileIndex].d;
-    float filterRadius = diffusionProfiles[diffusionProfileIndex].filterRadius;
+	float  distScale   = 1.;
+	vec3 S             = diffusionS[diffusionProfileIndex];
+	float  d           = diffusionD[diffusionProfileIndex];
+    float filterRadius = filterRadii[diffusionProfileIndex];
 
 	// Reconstruct the view-space position corresponding to the central sample.
 	vec2 centerPosNDC = vUV;

+ 7 - 114
src/scene.ts

@@ -21,14 +21,10 @@ import { AbstractScene } from "./abstractScene";
 import { BaseTexture } from "./Materials/Textures/baseTexture";
 import { Texture } from "./Materials/Textures/texture";
 import { RenderTargetTexture } from "./Materials/Textures/renderTargetTexture";
-import { MultiRenderTarget } from "./Materials/Textures/multiRenderTarget";
-import { SceneCompositorPostProcess } from "./PostProcesses/sceneCompositorPostProcess";
-import { SubSurfaceScatteringPostProcess } from "./PostProcesses/subSurfaceScatteringPostProcess";
 import { Material } from "./Materials/material";
 import { ImageProcessingConfiguration } from "./Materials/imageProcessingConfiguration";
 import { Effect } from "./Materials/effect";
 import { UniformBuffer } from "./Materials/uniformBuffer";
-import { PBRBaseMaterial } from "./Materials/PBR/pbrBaseMaterial";
 import { MultiMaterial } from "./Materials/multiMaterial";
 import { Light } from "./Lights/light";
 import { PickingInfo } from "./Collisions/pickingInfo";
@@ -256,56 +252,6 @@ export class Scene extends AbstractScene implements IAnimatable {
         return this._imageProcessingConfiguration;
     }
 
-    private _highDefinitionPipeline: boolean = false;
-
-    public get highDefinitionPipeline() {
-        return this._highDefinitionPipeline;
-    }
-
-    public set highDefinitionPipeline(b: boolean) {
-        this._highDefinitionPipeline = b;
-    }
-
-    private _isDeferredDirty: boolean = false;
-    public markDeferredDirty() {
-        this._isDeferredDirty = true;
-    }
-
-    private _updateDeferred() {
-        this.highDefinitionPipeline = false;
-
-        // Subsurface scattering
-        for (let i = 0; i < this.materials.length; i++) {
-            const material = this.materials[i] as PBRBaseMaterial;
-
-            if (material.subSurface && material.subSurface.isScatteringEnabled) {
-                this.highDefinitionPipeline = true;
-            }
-        }
-
-        // SSAO 2
-        // TODO
-
-        this._isDeferredDirty = false;
-
-        if (!this.highDefinitionPipeline) {
-            this._engine.renderToAttachments(this.defaultAttachments);
-        }
-    }
-
-    public mrtCount: number = 4;
-    public highDefinitionMRT: MultiRenderTarget;
-    private mrtTypes = [
-        Constants.TEXTURETYPE_UNSIGNED_INT, // Original color
-        Constants.TEXTURETYPE_HALF_FLOAT, // Irradiance
-        Constants.TEXTURETYPE_HALF_FLOAT, // Depth (world units)
-        Constants.TEXTURETYPE_UNSIGNED_INT
-    ];
-    private multiRenderAttachments: any[];
-    private defaultAttachments: any[];
-    public sceneCompositorPostProcess: SceneCompositorPostProcess;
-    public subSurfaceScatteringPostProcess: SubSurfaceScatteringPostProcess;
-
     private _forceWireframe = false;
     /**
      * Gets or sets a boolean indicating if all rendering must be done in wireframe
@@ -944,6 +890,11 @@ export class Scene extends AbstractScene implements IAnimatable {
     */
     public fogEnd = 1000.0;
 
+    /**
+    * Flag indicating that the frame buffer binding is handled by another component
+    */
+    public doNotBindFrameBuffer : boolean = false;
+
     // Lights
     private _shadowsEnabled = true;
     /**
@@ -1487,17 +1438,6 @@ export class Scene extends AbstractScene implements IAnimatable {
         if (!options || !options.virtual) {
             this._engine.onNewSceneAddedObservable.notifyObservers(this);
         }
-
-        this.highDefinitionMRT = new MultiRenderTarget("sceneHighDefinitionMRT", { width: engine.getRenderWidth(), height: engine.getRenderHeight() }, this.mrtCount, this,
-            { generateMipMaps: false, generateDepthTexture: true, defaultType: Constants.TEXTURETYPE_UNSIGNED_INT, types: this.mrtTypes });
-        this.highDefinitionMRT.samples = 1;
-
-        let gl = this._engine._gl;
-        this.multiRenderAttachments = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3];
-        this.defaultAttachments = [gl.COLOR_ATTACHMENT0, gl.NONE, gl.NONE, gl.NONE];
-        this.sceneCompositorPostProcess = new SceneCompositorPostProcess("sceneCompositor", 1, null, undefined, this._engine);
-        this.sceneCompositorPostProcess.inputTexture = this.highDefinitionMRT.getInternalTexture()!;
-        this.subSurfaceScatteringPostProcess = new SubSurfaceScatteringPostProcess("subSurfaceScattering", this, 1, null, undefined, this._engine);
     }
 
     /**
@@ -3699,40 +3639,7 @@ export class Scene extends AbstractScene implements IAnimatable {
         this.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(force));
     }
 
-    public drawBuffers(effect: Effect) {
-        if (this.highDefinitionPipeline) {
-            if (effect._multiTarget) {
-                this._engine.renderToAttachments(this.multiRenderAttachments);
-            } else {
-                this._engine.renderToAttachments(this.defaultAttachments);      
-            }
-        }
-    }
-
-    private _checkRTSize() {
-        var requiredWidth = this._engine.getRenderWidth(true);
-        var requiredHeight = this._engine.getRenderHeight(true);
-        var width = this.highDefinitionMRT.getRenderWidth();
-        var height = this.highDefinitionMRT.getRenderHeight();
-
-        if (width !== requiredWidth || height !== requiredHeight) {
-            this.highDefinitionMRT.resize({ width: requiredWidth, height: requiredHeight });
-            this.sceneCompositorPostProcess.inputTexture = this.highDefinitionMRT.getInternalTexture()!;
-        }
-    }
-
     private _bindFrameBuffer() {
-        if (this.highDefinitionPipeline) {
-            this._checkRTSize();
-            var internalTexture = this.highDefinitionMRT.getInternalTexture();
-            if (internalTexture) {
-                this.getEngine().bindFramebuffer(internalTexture);
-            } else {
-                Logger.Error("High Definition pipeline error.");
-            }
-            return;
-        }
-
         if (this.activeCamera && this.activeCamera._multiviewTexture) {
             this.activeCamera._multiviewTexture._bindFrameBuffer();
         } else if (this.activeCamera && this.activeCamera.outputRenderTarget) {
@@ -3842,19 +3749,15 @@ export class Scene extends AbstractScene implements IAnimatable {
             }
         }
 
-        if (this._isDeferredDirty) {
-            this._updateDeferred();
-        }
-
         // Restore framebuffer after rendering to targets
-        if (needRebind || this.highDefinitionPipeline) {
+        if (needRebind && !this.doNotBindFrameBuffer) {
             this._bindFrameBuffer();
         }
 
         this.onAfterRenderTargetsRenderObservable.notifyObservers(this);
 
         // Prepare Frame
-        if (this.postProcessManager && !camera._multiviewTexture) {
+        if (this.postProcessManager && !camera._multiviewTexture && !this.doNotBindFrameBuffer) {
             this.postProcessManager._prepareFrame();
         }
 
@@ -3873,16 +3776,6 @@ export class Scene extends AbstractScene implements IAnimatable {
             step.action(this.activeCamera);
         }
 
-        if (this.highDefinitionPipeline) {
-            // this.sceneCompositorPostProcess.activate(this.activeCamera);
-            this.sceneCompositorPostProcess.autoClear = false;
-            this.sceneCompositorPostProcess.activate(this.activeCamera);
-            this.subSurfaceScatteringPostProcess.activate(this.activeCamera);
-            this.postProcessManager.directRender([this.sceneCompositorPostProcess], this.subSurfaceScatteringPostProcess.inputTexture);
-            // this.getEngine().restoreDefaultFramebuffer(); // Restore back buffer if needed
-            this.postProcessManager.directRender([this.subSurfaceScatteringPostProcess]);
-        }
-
         // Finalize frame
         if (this.postProcessManager && !camera._multiviewTexture) {
             this.postProcessManager._finalizeFrame(camera.isIntermediate);

+ 3 - 0
src/sceneComponent.ts

@@ -24,6 +24,7 @@ export class SceneComponentConstants {
     public static readonly NAME_GAMEPAD = "Gamepad";
     public static readonly NAME_SIMPLIFICATIONQUEUE = "SimplificationQueue";
     public static readonly NAME_GEOMETRYBUFFERRENDERER = "GeometryBufferRenderer";
+    public static readonly NAME_PREPASSRENDERER = "PrePassRenderer";
     public static readonly NAME_DEPTHRENDERER = "DepthRenderer";
     public static readonly NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";
     public static readonly NAME_SPRITE = "Sprite";
@@ -46,6 +47,7 @@ export class SceneComponentConstants {
 
     public static readonly STEP_BEFORECAMERADRAW_EFFECTLAYER = 0;
     public static readonly STEP_BEFORECAMERADRAW_LAYER = 1;
+    public static readonly STEP_BEFORECAMERADRAW_PREPASS = 2;
 
     public static readonly STEP_BEFORERENDERTARGETDRAW_LAYER = 0;
 
@@ -67,6 +69,7 @@ export class SceneComponentConstants {
     public static readonly STEP_AFTERCAMERADRAW_LENSFLARESYSTEM = 1;
     public static readonly STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW = 2;
     public static readonly STEP_AFTERCAMERADRAW_LAYER = 3;
+    public static readonly STEP_AFTERCAMERADRAW_PREPASS = 4;
 
     public static readonly STEP_AFTERRENDER_AUDIO = 0;