浏览代码

scene component OK

Benjamin Guignabert 5 年之前
父节点
当前提交
cafe62f014

+ 6 - 8
src/Engines/Extensions/engine.multiRender.ts

@@ -38,11 +38,12 @@ declare module "../../Engines/thinEngine" {
         updateMultipleRenderTargetTextureSampleCount(count: number, textures: Nullable<InternalTexture[]>, samples: number): number;
 
         /**
-         * Clears attachments from index 1 to last index.
-         * @param color Clear color
+         * Clears attachments
+         * @param texture texture to clear
          * @param attachments attachments to clear
+         * @param color Clear color
          */
-        clearColorAttachments(texture: InternalTexture, color?: IColor4Like) : void;
+        clearColorAttachments(texture: InternalTexture, attachments: number[], color?: IColor4Like) : void;
 
         /**
          * Select a subsets of attachments to draw to.
@@ -58,14 +59,10 @@ ThinEngine.prototype.renderToAttachments = function(attachments: any[]): void {
     gl.drawBuffers(attachments);
 };
 
-ThinEngine.prototype.clearColorAttachments = function(texture: InternalTexture, color?: IColor4Like): void {
+ThinEngine.prototype.clearColorAttachments = function(texture: InternalTexture, attachments: number[], color?: IColor4Like): void {
     // Default clear everything to transparent black
     const gl = this._gl;
 
-    // Texture created with createMultipleRenderTarget should have its attachments
-    const attachments = texture._attachments!.slice(0);
-    attachments[0] = gl.NONE;
-
     // We don't clear the first attachments which is cleared with the user clear color
     gl.drawBuffers(attachments);
     if (color) {
@@ -76,6 +73,7 @@ ThinEngine.prototype.clearColorAttachments = function(texture: InternalTexture,
 
     gl.clear(gl.COLOR_BUFFER_BIT);
 
+    // Restore default attachments
     gl.drawBuffers(texture._attachments!);
 };
 

+ 1 - 5
src/Engines/thinEngine.ts

@@ -1145,7 +1145,7 @@ export class ThinEngine {
      * @param depth defines if the depth buffer must be cleared
      * @param stencil defines if the stencil buffer must be cleared
      */
-    public clear(color: Nullable<IColor4Like>, backBuffer: boolean, depth: boolean, stencil: boolean = false, texture?: InternalTexture): void {
+    public clear(color: Nullable<IColor4Like>, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
         this.applyStates();
 
         var mode = 0;
@@ -1168,10 +1168,6 @@ export class ThinEngine {
             mode |= this._gl.STENCIL_BUFFER_BIT;
         }
         this._gl.clear(mode);
-
-        if (texture) {
-            this.clearColorAttachments(texture);
-        }
     }
 
     private _viewportCached = { x: 0, y: 0, z: 0, w: 0 };

+ 4 - 3
src/Materials/PBR/pbrBaseMaterial.ts

@@ -1319,8 +1319,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         // Multiview
         MaterialHelper.PrepareDefinesForMultiview(scene, defines);
 
-        // Deferred
-        MaterialHelper.PrepareDefinesForDeferred(scene, defines, this.shouldRenderToMRT);
+        // PrePass
+        MaterialHelper.PrepareDefinesForPrePass(scene, defines, this.shouldRenderToMRT);
 
         // Textures
         defines.METALLICWORKFLOW = this.isMetallicWorkflow();
@@ -1576,7 +1576,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         }
 
         if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
-            this._imageProcessingConfiguration.prepareDefines(defines, false, this.getScene().highDefinitionPipeline);
+            const prePassRenderer = this.getScene()._prePassRenderer;
+            this._imageProcessingConfiguration.prepareDefines(defines, false, prePassRenderer ? prePassRenderer.enabled : false);
         }
 
         defines.FORCENORMALFORWARD = this._forceNormalForward;

+ 3 - 3
src/Materials/imageProcessingConfiguration.ts

@@ -438,8 +438,8 @@ export class ImageProcessingConfiguration {
      * @param defines the list of defines to complete
      * @param forPostProcess Define if we are currently in post process mode or not
      */
-    public prepareDefines(defines: IImageProcessingConfigurationDefines, forPostProcess: boolean = false, compositionPipeline: boolean = false): void {
-        if (forPostProcess !== this.applyByPostProcess || !this._isEnabled || compositionPipeline) {
+    public prepareDefines(defines: IImageProcessingConfigurationDefines, forPostProcess: boolean = false, prePassEnabled: boolean = false): void {
+        if (forPostProcess !== this.applyByPostProcess || !this._isEnabled || prePassEnabled) {
             defines.VIGNETTE = false;
             defines.TONEMAPPING = false;
             defines.TONEMAPPING_ACES = false;
@@ -449,7 +449,7 @@ export class ImageProcessingConfiguration {
             defines.COLORGRADING = false;
             defines.COLORGRADING3D = false;
             defines.IMAGEPROCESSING = false;
-            defines.IMAGEPROCESSINGPOSTPROCESS = compositionPipeline || (this.applyByPostProcess && this._isEnabled);
+            defines.IMAGEPROCESSINGPOSTPROCESS = prePassEnabled || (this.applyByPostProcess && this._isEnabled);
             return;
         }
 

+ 3 - 3
src/Materials/materialHelper.ts

@@ -300,12 +300,12 @@ export class MaterialHelper {
      * @param scene The scene we are intending to draw
      * @param defines The defines to update
      */
-    public static PrepareDefinesForDeferred(scene: Scene, defines: any, shouldRenderToMRT: boolean) {
+    public static PrepareDefinesForPrePass(scene: Scene, defines: any, shouldRenderToMRT: boolean) {
         var previousDeferred = defines.HIGH_DEFINITION_PIPELINE;
 
-        if (scene.highDefinitionPipeline && shouldRenderToMRT) {
+        if (scene.prePassRenderer && shouldRenderToMRT) {
             defines.HIGH_DEFINITION_PIPELINE = true;
-            defines.SCENE_MRT_COUNT = scene.mrtCount;
+            defines.SCENE_MRT_COUNT = scene.prePassRenderer.mrtCount;
         } else {
             defines.HIGH_DEFINITION_PIPELINE = false;
         }

+ 3 - 1
src/Meshes/mesh.ts

@@ -1832,7 +1832,9 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
         }
 
         // Render to MRT
-        scene.drawBuffers(effect);
+        if (scene.prePassRenderer) {
+            scene.prePassRenderer.drawBuffers(effect);
+        }
 
         const effectiveMesh = effectiveMeshReplacement || this._effectiveMesh;
 

+ 7 - 3
src/PostProcesses/SubSurfaceScatteringPostProcess.ts

@@ -36,12 +36,16 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
         this.addDiffusionProfile(new Color3(1, 1, 1));
 
         this.onApplyObservable.add((effect: Effect) => {
+            if (!scene.prePassRenderer) {
+                Logger.Error("PrePass needs to be enabled for subsurface scattering.");
+                return;
+            }
             var texelSize = this.texelSize;
             effect.setFloat("metersPerUnit", scene.metersPerUnit);
             effect.setFloat2("texelSize", texelSize.x, texelSize.y);
-            effect.setTexture("irradianceSampler", scene.highDefinitionMRT.textures[1]);
-            effect.setTexture("depthSampler", scene.highDefinitionMRT.textures[2]);
-            effect.setTexture("albedoSampler", scene.highDefinitionMRT.textures[3]);
+            effect.setTexture("irradianceSampler", scene.prePassRenderer.prePassRT.textures[1]);
+            effect.setTexture("depthSampler", scene.prePassRenderer.prePassRT.textures[2]);
+            effect.setTexture("albedoSampler", scene.prePassRenderer.prePassRT.textures[3]);
             effect.setFloat2("viewportSize",
                 Math.tan(scene.activeCamera!.fov / 2) * scene.getEngine().getAspectRatio(scene.activeCamera!, true),
                 Math.tan(scene.activeCamera!.fov / 2));

+ 0 - 119
src/Rendering/deferredSceneComponent.ts

@@ -1,119 +0,0 @@
-import { Nullable } from "../types";
-import { Scene } from "../scene";
-import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
-import { PrePassRenderer } from "./prePassRenderer";
-
-declare module "../scene" {
-    export interface Scene {
-        /** @hidden (Backing field) */
-        _prePassRenderer: Nullable<PrePassRenderer>;
-
-        /**
-         * Gets or Sets the current geometry buffer associated to the scene.
-         */
-        prePassRenderer: Nullable<PrePassRenderer>;
-
-        /**
-         * Enables the prepass and associates it with the scene
-         * @returns the PrePassRenderer
-         */
-        enablePrepassRenderer(ratio?: number): Nullable<PrePassRenderer>;
-
-        /**
-         * Disables the prepass associated with the scene
-         */
-        disablePrepassRenderer(): void;
-    }
-}
-
-Object.defineProperty(Scene.prototype, "PrePassRenderer", {
-    get: function(this: Scene) {
-        this._prePassRenderer;
-    },
-    set: function(this: Scene, value: Nullable<PrePassRenderer>) {
-        if (value && value.isSupported) {
-            this._prePassRenderer = value;
-        }
-    },
-    enumerable: true,
-    configurable: true
-});
-
-Scene.prototype.enablePrepassRenderer = function(ratio: number = 1): Nullable<PrePassRenderer> {
-    if (this._prePassRenderer) {
-        return this._prePassRenderer;
-    }
-
-    this._prePassRenderer = new PrePassRenderer(this);
-    if (!this._prePassRenderer.isSupported) {
-        this._prePassRenderer = null;
-    }
-
-    return this._prePassRenderer;
-};
-
-Scene.prototype.disablePrepassRenderer = function(): void {
-    if (!this._prePassRenderer) {
-        return;
-    }
-
-    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 PrePassSceneComponent implements ISceneComponent {
-    /**
-     * The component name helpful to identify the component in the list of scene components.
-     */
-    public readonly name = SceneComponentConstants.NAME_PREPASSRENDERER;
-
-    /**
-     * The scene the component belongs to.
-     */
-    public scene: Scene;
-
-    /**
-     * Creates a new instance of the component for the given scene
-     * @param scene Defines the scene to register the component in
-     */
-    constructor(scene: Scene) {
-        this.scene = scene;
-    }
-
-    /**
-     * Registers the component in a given scene
-     */
-    public register(): void {
-        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);
-    }
-
-    /**
-     * Rebuilds the elements related to this component in case of
-     * context lost for instance.
-     */
-    public rebuild(): void {
-        // Nothing to do for this component
-    }
-
-    /**
-     * Disposes the component and the associated ressources
-     */
-    public dispose(): void {
-        // Nothing to do for this component
-    }
-
-}
-
-PrePassRenderer._SceneComponentInitialization = (scene: Scene) => {
-    // Register the G Buffer component to the scene.
-    let component = scene._getComponent(SceneComponentConstants.NAME_PREPASSRENDERER) as PrePassSceneComponent;
-    if (!component) {
-        component = new PrePassSceneComponent(scene);
-        scene._addComponent(component);
-    }
-};

+ 2 - 0
src/Rendering/index.ts

@@ -4,6 +4,8 @@ export * from "./depthRendererSceneComponent";
 export * from "./edgesRenderer";
 export * from "./geometryBufferRenderer";
 export * from "./geometryBufferRendererSceneComponent";
+export * from "./prePassRenderer";
+export * from "./prePassRendererSceneComponent";
 export * from "./outlineRenderer";
 export * from "./renderingGroup";
 export * from "./renderingManager";

+ 31 - 10
src/Rendering/prePassRenderer.ts

@@ -27,8 +27,9 @@ export class PrePassRenderer {
         Constants.TEXTURETYPE_HALF_FLOAT, // Depth (world units)
         Constants.TEXTURETYPE_UNSIGNED_INT
     ];
-    private _multiRenderAttachments: any[];
-    private _defaultAttachments: any[];
+    private _multiRenderAttachments: number[];
+    private _defaultAttachments: number[];
+    private _clearAttachments: number[];
 
     public sceneCompositorPostProcess: SceneCompositorPostProcess;
     public subSurfaceScatteringPostProcess: SubSurfaceScatteringPostProcess;
@@ -38,10 +39,6 @@ export class PrePassRenderer {
         return this._enabled;
     }
 
-    public set enabled(b: boolean) {
-        this._enabled = b;
-    }
-
     constructor(scene: Scene) {
         this._scene = scene;
         this._engine = scene.getEngine();
@@ -51,11 +48,14 @@ export class PrePassRenderer {
         this.prePassRT.samples = 1;
 
         let gl = this._engine._gl;
+        this._clearAttachments = [gl.NONE, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3];
         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.prePassRT.getInternalTexture()!;
         this.subSurfaceScatteringPostProcess = new SubSurfaceScatteringPostProcess("subSurfaceScattering", this._scene, 1, null, undefined, this._engine);
+
+        PrePassRenderer._SceneComponentInitialization(this._scene);
     }
 
     public get isSupported() {
@@ -89,8 +89,8 @@ export class PrePassRenderer {
             this.subSurfaceScatteringPostProcess.activate(this._scene.activeCamera);
             this._scene.postProcessManager.directRender([this.sceneCompositorPostProcess], this.subSurfaceScatteringPostProcess.inputTexture);
             // this.getEngine().restoreDefaultFramebuffer(); // Restore back buffer if needed
-            this._scene.postProcessManager._prepareFrame();
-            this._scene.postProcessManager.directRender([this.subSurfaceScatteringPostProcess], null, false, 0, 0, true);
+            // this._scene.postProcessManager._prepareFrame();
+            this._scene.postProcessManager.directRender([this.subSurfaceScatteringPostProcess], null, false, 0, 0, false);
         }
     }
 
@@ -119,19 +119,40 @@ export class PrePassRenderer {
         }
     }
 
+    public clear() {
+        if (this._enabled) {
+            this._bindFrameBuffer();
+            this._engine.clear(this._scene.clearColor,
+                this._scene.autoClear || this._scene.forceWireframe || this._scene.forcePointsCloud,
+                this._scene.autoClearDepthAndStencil,
+                this._scene.autoClearDepthAndStencil);
+            this._engine.clearColorAttachments(this.prePassRT.getInternalTexture()!, this._clearAttachments);
+        }
+    }
+
+    private _enable() {
+        this._enabled = true;
+        this._scene.prePass = true;
+    }
+
+    private _disable() {
+        this._enabled = false;
+        this._scene.prePass = false;
+    }
+
     public markAsDirty() {
         this._isDirty = true;
     }
 
     private _update() {
-        this.enabled = false;
+        this._disable();
 
         // Subsurface scattering
         for (let i = 0; i < this._scene.materials.length; i++) {
             const material = this._scene.materials[i] as PBRBaseMaterial;
 
             if (material.subSurface && material.subSurface.isScatteringEnabled) {
-                this.enabled = true;
+                this._enable();
             }
         }
 

+ 6 - 7
src/scene.ts

@@ -893,7 +893,7 @@ export class Scene extends AbstractScene implements IAnimatable {
     /**
     * Flag indicating that the frame buffer binding is handled by another component
     */
-    public doNotBindFrameBuffer : boolean = false;
+    public prePass : boolean = false;
 
     // Lights
     private _shadowsEnabled = true;
@@ -3750,14 +3750,14 @@ export class Scene extends AbstractScene implements IAnimatable {
         }
 
         // Restore framebuffer after rendering to targets
-        if (needRebind && !this.doNotBindFrameBuffer) {
+        if (needRebind && !this.prePass) {
             this._bindFrameBuffer();
         }
 
         this.onAfterRenderTargetsRenderObservable.notifyObservers(this);
 
         // Prepare Frame
-        if (this.postProcessManager && !camera._multiviewTexture && !this.doNotBindFrameBuffer) {
+        if (this.postProcessManager && !camera._multiviewTexture && !this.prePass) {
             this.postProcessManager._prepareFrame();
         }
 
@@ -4029,7 +4029,7 @@ export class Scene extends AbstractScene implements IAnimatable {
 
         // Restore back buffer
         this.activeCamera = currentActiveCamera;
-        if (this._activeCamera && this._activeCamera.cameraRigMode !== Camera.RIG_MODE_CUSTOM) {
+        if (this._activeCamera && this._activeCamera.cameraRigMode !== Camera.RIG_MODE_CUSTOM && !this.prePass) {
             this._bindFrameBuffer();
         }
         this.onAfterRenderTargetsRenderObservable.notifyObservers(this);
@@ -4039,12 +4039,11 @@ export class Scene extends AbstractScene implements IAnimatable {
         }
 
         // Clear
-        if (this.autoClearDepthAndStencil || this.autoClear) {
+        if ((this.autoClearDepthAndStencil || this.autoClear) && !this.prePass) {
             this._engine.clear(this.clearColor,
                 this.autoClear || this.forceWireframe || this.forcePointsCloud,
                 this.autoClearDepthAndStencil,
-                this.autoClearDepthAndStencil,
-                this.highDefinitionPipeline ? this.highDefinitionMRT._texture! : undefined);
+                this.autoClearDepthAndStencil);
         }
 
         // Collects render targets from external components.

+ 2 - 0
src/sceneComponent.ts

@@ -80,6 +80,8 @@ export class SceneComponentConstants {
 
     public static readonly STEP_GATHERACTIVECAMERARENDERTARGETS_DEPTHRENDERER = 0;
 
+    public static readonly STEP_BEFORECLEARSTAGE_PREPASS = 0;
+
     public static readonly STEP_POINTERMOVE_SPRITE = 0;
     public static readonly STEP_POINTERDOWN_SPRITE = 0;
     public static readonly STEP_POINTERUP_SPRITE = 0;