Bläddra i källkod

Merge pull request #4735 from sebavan/master

Fix #4729: Rendering group setup is not shared with the scene
David Catuhe 7 år sedan
förälder
incheckning
a093589fa0

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

@@ -158,3 +158,4 @@
 ## Breaking changes
 
 - Fixing support for R and RG texture formats made us remove TextureFormat_R32F and TextureFormat_RG32F as they were mixing formats and types. Please, use the respective TextureFormat_R and TextureFormat_RG with the Float types ([sebavan](http://www.github.com/sebavan))
+- Replacing `scene.onRenderingGroupObservable` by `onBeforeRenderingGroupObservable` and `onAfterRenderingGroupObservable` to prevent the stage check ([sebavan](http://www.github.com/sebavan))

+ 2 - 0
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -197,6 +197,7 @@
 
             // Rendering groups
             this._renderingManager = new RenderingManager(scene);
+            this._renderingManager._useSceneAutoClearSetup = true;
 
             if (isMulti) {
                 return;
@@ -671,6 +672,7 @@
          */
         public setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void {
             this._renderingManager.setRenderingAutoClearDepthStencil(renderingGroupId, autoClearDepthStencil);
+            this._renderingManager._useSceneAutoClearSetup = false;
         }
 
         public clone(): RenderTargetTexture {

+ 9 - 0
src/Mesh/babylon.linesMesh.ts

@@ -74,14 +74,23 @@
             return "LinesMesh";
         }
 
+        /**
+         * @hidden
+         */
         public get material(): Material {
             return this._colorShader;
         }
 
+        /**
+         * @hidden
+         */
         public set material(value: Material) {
             // Do nothing
         }
 
+        /**
+         * @hidden
+         */
         public get checkCollisions(): boolean {
             return false;
         }

+ 50 - 46
src/Rendering/babylon.renderingManager.ts

@@ -4,9 +4,18 @@
      * Interface describing the different options available in the rendering manager
      * regarding Auto Clear between groups.
      */
-    interface RenderingManageAutoClearOptions {
+    export interface IRenderingManagerAutoClearSetup {
+        /**
+         * Defines whether or not autoclear is enable.
+         */
         autoClear: boolean;
+        /**
+         * Defines whether or not to autoclear the depth buffer.
+         */
         depth: boolean;
+        /**
+         * Defines whether or not to autoclear the stencil buffer.
+         */
         stencil: boolean;
     }
 
@@ -26,15 +35,20 @@
          */
         public static AUTOCLEAR = true;
 
+        /**
+         * Hidden
+         */
+        public _useSceneAutoClearSetup = false;
+
         private _scene: Scene;
         private _renderingGroups = new Array<RenderingGroup>();
         private _depthStencilBufferAlreadyCleaned: boolean;
-
-        private _autoClearDepthStencil: { [id: number]: RenderingManageAutoClearOptions } = {};
+        
+        private _autoClearDepthStencil: { [id: number]: IRenderingManagerAutoClearSetup } = {};
         private _customOpaqueSortCompareFn: { [id: number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
         private _customAlphaTestSortCompareFn: { [id: number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
         private _customTransparentSortCompareFn: { [id: number]: Nullable<(a: SubMesh, b: SubMesh) => number> } = {};
-        private _renderinGroupInfo: Nullable<RenderingGroupInfo> = null;
+        private _renderingGroupInfo: Nullable<RenderingGroupInfo> = new RenderingGroupInfo();
 
         constructor(scene: Scene) {
             this._scene = scene;
@@ -56,17 +70,10 @@
         public render(customRenderFunction: Nullable<(opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void>,
             activeMeshes: Nullable<AbstractMesh[]>, renderParticles: boolean, renderSprites: boolean): void {
 
-            // Check if there's at least on observer on the onRenderingGroupObservable and initialize things to fire it
-            let observable = this._scene.onRenderingGroupObservable.hasObservers() ? this._scene.onRenderingGroupObservable : null;
-            let info: Nullable<RenderingGroupInfo> = null;
-            if (observable) {
-                if (!this._renderinGroupInfo) {
-                    this._renderinGroupInfo = new RenderingGroupInfo();
-                }
-                info = this._renderinGroupInfo;
-                info.scene = this._scene;
-                info.camera = this._scene.activeCamera;
-            }
+            // Update the observable context (not null as it only goes away on dispose)
+            const info = this._renderingGroupInfo!;
+            info.scene = this._scene;
+            info.camera = this._scene.activeCamera;
 
             // Dispatch sprites
             if (renderSprites) {
@@ -80,51 +87,37 @@
             for (let index = RenderingManager.MIN_RENDERINGGROUPS; index < RenderingManager.MAX_RENDERINGGROUPS; index++) {
                 this._depthStencilBufferAlreadyCleaned = index === RenderingManager.MIN_RENDERINGGROUPS;
                 var renderingGroup = this._renderingGroups[index];
-                if (!renderingGroup && !observable)
+                if (!renderingGroup)
                     continue;
 
-                let renderingGroupMask = 0;
+                let renderingGroupMask = Math.pow(2, index);
+                info.renderingGroupId = index;
 
-                // Fire PRECLEAR stage
-                if (observable && info) {
-                    renderingGroupMask = Math.pow(2, index);
-                    info.renderStage = RenderingGroupInfo.STAGE_PRECLEAR;
-                    info.renderingGroupId = index;
-                    observable.notifyObservers(info, renderingGroupMask);
-                }
+                // Before Observable
+                this._scene.onBeforeRenderingGroupObservable.notifyObservers(info, renderingGroupMask);
 
                 // Clear depth/stencil if needed
                 if (RenderingManager.AUTOCLEAR) {
-                    let autoClear = this._autoClearDepthStencil[index];
+                    const autoClear = this._useSceneAutoClearSetup ? 
+                        this._scene.getAutoClearDepthStencilSetup(index) :
+                        this._autoClearDepthStencil[index];
+
                     if (autoClear && autoClear.autoClear) {
                         this._clearDepthStencilBuffer(autoClear.depth, autoClear.stencil);
                     }
                 }
 
-                if (observable && info) {
-                    // Fire PREOPAQUE stage
-                    info.renderStage = RenderingGroupInfo.STAGE_PREOPAQUE;
-                    observable.notifyObservers(info, renderingGroupMask);
-                    // Fire PRETRANSPARENT stage
-                    info.renderStage = RenderingGroupInfo.STAGE_PRETRANSPARENT;
-                    observable.notifyObservers(info, renderingGroupMask);
+                // Render
+                for (let step of this._scene._beforeRenderingGroupDrawStage) {
+                    step.action(index);
                 }
-
-                if (renderingGroup) {
-                    for (let step of this._scene._beforeRenderingGroupDrawStage) {
-                        step.action(index);
-                    }
-                    renderingGroup.render(customRenderFunction, renderSprites, renderParticles, activeMeshes);
-                    for (let step of this._scene._afterRenderingGroupDrawStage) {
-                        step.action(index);
-                    }
+                renderingGroup.render(customRenderFunction, renderSprites, renderParticles, activeMeshes);
+                for (let step of this._scene._afterRenderingGroupDrawStage) {
+                    step.action(index);
                 }
 
-                // Fire POSTTRANSPARENT stage
-                if (observable && info) {
-                    info.renderStage = RenderingGroupInfo.STAGE_POSTTRANSPARENT;
-                    observable.notifyObservers(info, renderingGroupMask);
-                }
+                // After Observable
+                this._scene.onAfterRenderingGroupObservable.notifyObservers(info, renderingGroupMask);
             }
         }
 
@@ -140,6 +133,7 @@
         public dispose(): void {
             this.freeRenderingGroups();
             this._renderingGroups.length = 0;
+            this._renderingGroupInfo = null;
         }
 
         /**
@@ -239,5 +233,15 @@
                 stencil: stencil
             };
         }
+
+        /**
+         * Gets the current auto clear configuration for one rendering group of the rendering
+         * manager.
+         * @param index the rendering group index to get the information for
+         * @returns The auto clear setup for the requested rendering group
+         */
+        public getAutoClearDepthStencilSetup(index: number): IRenderingManagerAutoClearSetup {
+            return this._autoClearDepthStencil[index];
+        }
     }
 } 

+ 21 - 31
src/babylon.scene.ts

@@ -77,35 +77,6 @@
          * The ID of the renderingGroup being processed
          */
         renderingGroupId: number;
-
-        /**
-         * The rendering stage, can be either STAGE_PRECLEAR, STAGE_PREOPAQUE, STAGE_PRETRANSPARENT, STAGE_POSTTRANSPARENT
-         */
-        renderStage: number;
-
-        /**
-         * Stage corresponding to the very first hook in the renderingGroup phase: before the render buffer may be cleared
-         * This stage will be fired no matter what
-         */
-        static STAGE_PRECLEAR = 1;
-
-        /**
-         * Called before opaque object are rendered.
-         * This stage will be fired only if there's 3D Opaque content to render
-         */
-        static STAGE_PREOPAQUE = 2;
-
-        /**
-         * Called after the opaque objects are rendered and before the transparent ones
-         * This stage will be fired only if there's 3D transparent content to render
-         */
-        static STAGE_PRETRANSPARENT = 3;
-
-        /**
-         * Called after the transparent object are rendered, last hook of the renderingGroup phase
-         * This stage will be fired no matter what
-         */
-        static STAGE_POSTTRANSPARENT = 4;
     }
 
     /**
@@ -532,11 +503,18 @@
         public onAfterStepObservable = new Observable<Scene>();
 
         /**
-         * This Observable will be triggered for each stage of each renderingGroup of each rendered camera.
+         * This Observable will be triggered before rendering each renderingGroup of each rendered camera.
+         * The RenderinGroupInfo class contains all the information about the context in which the observable is called
+         * If you wish to register an Observer only for a given set of renderingGroup, use the mask with a combination of the renderingGroup index elevated to the power of two (1 for renderingGroup 0, 2 for renderingrOup1, 4 for 2 and 8 for 3)
+         */
+        public onBeforeRenderingGroupObservable = new Observable<RenderingGroupInfo>();
+
+        /**
+         * This Observable will be triggered after rendering each renderingGroup of each rendered camera.
          * The RenderinGroupInfo class contains all the information about the context in which the observable is called
          * If you wish to register an Observer only for a given set of renderingGroup, use the mask with a combination of the renderingGroup index elevated to the power of two (1 for renderingGroup 0, 2 for renderingrOup1, 4 for 2 and 8 for 3)
          */
-        public onRenderingGroupObservable = new Observable<RenderingGroupInfo>();
+        public onAfterRenderingGroupObservable = new Observable<RenderingGroupInfo>();
 
         // Animations
         private _registeredForLateAnimationBindings = new SmartArrayNoDuplicate<any>(256);
@@ -5068,6 +5046,8 @@
             this.onBeforeAnimationsObservable.clear();
             this.onAfterAnimationsObservable.clear();
             this.onDataLoadedObservable.clear();
+            this.onBeforeRenderingGroupObservable.clear();
+            this.onAfterRenderingGroupObservable.clear();
 
             this.detachControl();
 
@@ -6007,6 +5987,16 @@
         }
 
         /**
+         * Gets the current auto clear configuration for one rendering group of the rendering
+         * manager.
+         * @param index the rendering group index to get the information for
+         * @returns The auto clear setup for the requested rendering group
+         */
+        public getAutoClearDepthStencilSetup(index: number): IRenderingManagerAutoClearSetup {
+            return this._renderingManager.getAutoClearDepthStencilSetup(index);
+        }
+
+        /**
          * Will flag all materials as dirty to trigger new shader compilation
          * @param flag defines the flag used to specify which material part must be marked as dirty
          * @param predicate If not null, it will be used to specifiy if a material has to be marked as dirty