= преди 9 години
родител
ревизия
f146a0d326

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

@@ -349,8 +349,8 @@
                 transparentSortCompareFn);
         }
 
-        public setRenderingAutoClear(renderingGroupId: number, autoClear: boolean) {            
-            this._renderingManager.setRenderingAutoClear(renderingGroupId, autoClear);
+        public setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClear: boolean) {            
+            this._renderingManager.setRenderingAutoClearDepthStencil(renderingGroupId, autoClear);
         }
 
         public clone(): RenderTargetTexture {

+ 12 - 2
src/PostProcess/babylon.postProcess.ts

@@ -174,10 +174,20 @@
                 }         
                 this.width = desiredWidth;
                 this.height = desiredHeight;
-                this._textures.push(this._engine.createRenderTargetTexture({ width: this.width, height: this.height }, { generateMipMaps: false, generateDepthBuffer: camera._postProcesses.indexOf(this) === 0, samplingMode: this.renderTargetSamplingMode, type: this._textureType }));
+
+                let textureSize = { width: this.width, height: this.height };
+                let textureOptions = { 
+                    generateMipMaps: false, 
+                    generateDepthBuffer: camera._postProcesses.indexOf(this) === 0, 
+                    generateStencilBuffer: camera._postProcesses.indexOf(this) === 0 && this._engine.isStencilEnable,
+                    samplingMode: this.renderTargetSamplingMode, 
+                    type: this._textureType 
+                };
+
+                this._textures.push(this._engine.createRenderTargetTexture(textureSize, textureOptions));
 
                 if (this._reusable) {
-                    this._textures.push(this._engine.createRenderTargetTexture({ width: this.width, height: this.height }, { generateMipMaps: false, generateDepthBuffer: camera._postProcesses.indexOf(this) === 0, samplingMode: this.renderTargetSamplingMode, type: this._textureType }));
+                    this._textures.push(this._engine.createRenderTargetTexture(textureSize, textureOptions));
                 }
 
                 this.onSizeChangedObservable.notifyObservers(this);

+ 75 - 65
src/Rendering/babylon.renderingGroup.ts

@@ -6,12 +6,46 @@
         private _alphaTestSubMeshes = new SmartArray<SubMesh>(256);
         private _activeVertices: number;
 
-        public opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number;
-        public alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number;
-        public transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number;
+        private _opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number;
+        private _alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number;
+        private _transparentSortCompareFn: (a: SubMesh, b: SubMesh) => number;
+        
+        private _renderOpaque: (subMeshes: SmartArray<SubMesh>) => void;
+        private _renderAlphaTest: (subMeshes: SmartArray<SubMesh>) => void;
+        private _renderTransparent: (subMeshes: SmartArray<SubMesh>) => void;
 
         public onBeforeTransparentRendering: () => void;
 
+        public set opaqueSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+            this._opaqueSortCompareFn = value;
+            if (value) {
+                this._renderOpaque = this.renderOpaqueSorted;
+            }
+            else {
+                this._renderOpaque = RenderingGroup.renderUnsorted;
+            }
+        }
+
+        public set alphaTestSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+            this._alphaTestSortCompareFn = value;
+            if (value) {
+                this._renderAlphaTest = this.renderAlphaTestSorted;
+            }
+            else {
+                this._renderAlphaTest = RenderingGroup.renderUnsorted;
+            }
+        }
+
+        public set transparentSortCompareFn(value: (a: SubMesh, b: SubMesh) => number) {
+            this._transparentSortCompareFn = value;
+            if (value) {
+                this._renderTransparent = this.renderTransparentSorted;
+            }
+            else {
+                this._renderTransparent = RenderingGroup.renderUnsorted;
+            }
+        }
+
         constructor(public index: number, scene: Scene,
             opaqueSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
             alphaTestSortCompareFn: (a: SubMesh, b: SubMesh) => number = null,
@@ -36,56 +70,13 @@
                 return false;
             }
             var engine = this._scene.getEngine();
+            
             // Opaque
-            var subIndex: number;
-            var submesh: SubMesh;
-            var sortedArray: SubMesh[];
-
-            if (this.opaqueSortCompareFn) {
-                for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
-                    submesh = this._opaqueSubMeshes.data[subIndex];
-                    submesh._alphaIndex = submesh.getMesh().alphaIndex;
-                    submesh._distanceToCamera = submesh.getBoundingInfo().boundingSphere.centerWorld.subtract(this._scene.activeCamera.globalPosition).length();
-                }
-
-                sortedArray = this._opaqueSubMeshes.data.slice(0, this._opaqueSubMeshes.length);
-                sortedArray.sort(this.opaqueSortCompareFn);
-
-                for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
-                    submesh = sortedArray[subIndex];
-                    submesh.render(false);
-                }
-            }
-            else {
-                for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
-                    submesh = this._opaqueSubMeshes.data[subIndex];
-                    submesh.render(false);
-                }
-            }
+            this._renderOpaque(this._opaqueSubMeshes);
 
             // Alpha test
             engine.setAlphaTesting(true);
-            if (this.alphaTestSortCompareFn) {
-                for (subIndex = 0; subIndex < this._alphaTestSubMeshes.length; subIndex++) {
-                    submesh = this._alphaTestSubMeshes.data[subIndex];
-                    submesh._alphaIndex = submesh.getMesh().alphaIndex;
-                    submesh._distanceToCamera = submesh.getBoundingInfo().boundingSphere.centerWorld.subtract(this._scene.activeCamera.globalPosition).length();
-                }
-
-                sortedArray = this._alphaTestSubMeshes.data.slice(0, this._alphaTestSubMeshes.length);
-                sortedArray.sort(this.alphaTestSortCompareFn);
-
-                for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
-                    submesh = sortedArray[subIndex];
-                    submesh.render(false);
-                }
-            }
-            else {
-                for (subIndex = 0; subIndex < this._alphaTestSubMeshes.length; subIndex++) {
-                    submesh = this._alphaTestSubMeshes.data[subIndex];
-                    submesh.render(false);
-                }
-            }
+            this._renderAlphaTest(this._alphaTestSubMeshes);
             engine.setAlphaTesting(false);
 
             if (this.onBeforeTransparentRendering) {
@@ -93,26 +84,45 @@
             }
 
             // Transparent
-            if (this._transparentSubMeshes.length) {
-                // Sorting
-                for (subIndex = 0; subIndex < this._transparentSubMeshes.length; subIndex++) {
-                    submesh = this._transparentSubMeshes.data[subIndex];
-                    submesh._alphaIndex = submesh.getMesh().alphaIndex;
-                    submesh._distanceToCamera = submesh.getBoundingInfo().boundingSphere.centerWorld.subtract(this._scene.activeCamera.globalPosition).length();
-                }
+            this._renderTransparent(this._transparentSubMeshes);
+            return true;
+        }
 
-                var sortedArray = this._transparentSubMeshes.data.slice(0, this._transparentSubMeshes.length);
-                sortedArray.sort(this.transparentSortCompareFn);
+        private renderOpaqueSorted(subMeshes: SmartArray<SubMesh>): void {
+            return RenderingGroup.renderSorted(subMeshes, this.opaqueSortCompareFn, this._scene.activeCamera.globalPosition);
+        }
 
-                // Rendering                
-                for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
-                    submesh = sortedArray[subIndex];
+        private renderAlphaTestSorted(subMeshes: SmartArray<SubMesh>): void {
+            return RenderingGroup.renderSorted(subMeshes, this.alphaTestSortCompareFn, this._scene.activeCamera.globalPosition);
+        }
 
-                    submesh.render(true);
-                }
-                engine.setAlphaMode(Engine.ALPHA_DISABLE);
+        private renderTransparentSorted(subMeshes: SmartArray<SubMesh>): void {
+            return RenderingGroup.renderSorted(subMeshes, this.transparentSortCompareFn, this._scene.activeCamera.globalPosition);
+        }
+
+        private static renderSorted(subMeshes: SmartArray<SubMesh>, sortCompareFn: (a: SubMesh, b: SubMesh) => number, cameraPosition: Vector3): void {
+            let subIndex = 0;
+            let subMesh;
+            for (; subIndex < subMeshes.length; subIndex++) {
+                subMesh = subMeshes.data[subIndex];
+                subMesh._alphaIndex = subMesh.getMesh().alphaIndex;
+                subMesh._distanceToCamera = subMesh.getBoundingInfo().boundingSphere.centerWorld.subtract(cameraPosition).length();
+            }
+
+            let sortedArray = subMeshes.data.slice(0, subMeshes.length);
+            sortedArray.sort(sortCompareFn);
+
+            for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
+                subMesh = sortedArray[subIndex];
+                subMesh.render(false);
+            }
+        }
+
+        private static renderUnsorted(subMeshes: SmartArray<SubMesh>): void {
+            for (var subIndex = 0; subIndex < subMeshes.length; subIndex++) {
+                let submesh = subMeshes.data[subIndex];
+                submesh.render(false);
             }
-            return true;
         }
 
         public static defaultTransparentSortCompare(a: SubMesh, b:SubMesh) : number {

+ 8 - 7
src/Rendering/babylon.renderingManager.ts

@@ -12,7 +12,7 @@
         private _currentRenderParticles: boolean;
         private _currentRenderSprites: boolean;
 
-        private _autoClear: { [id:number]: boolean } = {};
+        private _autoClearDepthStencil: { [id:number]: boolean } = {};
         private _customOpaqueSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
         private _customAlphaTestSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
         private _customTransparentSortCompareFn: { [id:number]: (a: SubMesh, b: SubMesh) => number } = {};
@@ -21,7 +21,7 @@
             this._scene = scene;
 
             for (let i = RenderingManager.MIN_RENDERINGGROUPS; i < RenderingManager.MAX_RENDERINGGROUPS; i++) {
-                this._autoClear[i] = true;
+                this._autoClearDepthStencil[i] = true;
             }
         }
 
@@ -106,7 +106,7 @@
                 this._currentIndex = index;
 
                 if (renderingGroup) {
-                    if (this._autoClear[index]) {
+                    if (this._autoClearDepthStencil[index]) {
                         this._clearDepthStencilBuffer();
                     }
 
@@ -130,11 +130,12 @@
         }
 
         public reset(): void {
-            this._renderingGroups.forEach((renderingGroup, index, array) => {
+            for (var index = RenderingManager.MIN_RENDERINGGROUPS; index < RenderingManager.MAX_RENDERINGGROUPS; index++) {
+                var renderingGroup = this._renderingGroups[index];
                 if (renderingGroup) {
                     renderingGroup.prepare();
                 }
-            });
+            }
         }
 
         public dispatch(subMesh: SubMesh): void {
@@ -169,8 +170,8 @@
             this._customTransparentSortCompareFn[renderingGroupId] = transparentSortCompareFn;
         }
 
-        public setRenderingAutoClear(renderingGroupId: number, autoClear: boolean) {            
-            this._autoClear[renderingGroupId] = autoClear;
+        public setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClear: boolean) {            
+            this._autoClearDepthStencil[renderingGroupId] = autoClear;
         }
     }
 } 

+ 180 - 0
src/States/babylon.stencilState.js

@@ -0,0 +1,180 @@
+var BABYLON;
+(function (BABYLON) {
+    var Internals;
+    (function (Internals) {
+        var _StencilState = (function () {
+            function _StencilState() {
+                this._isStencilTestDirty = false;
+                this._isStencilMaskDirty = false;
+                this._isStencilFuncDirty = false;
+                this._isStencilOpDirty = false;
+                this.reset();
+            }
+            Object.defineProperty(_StencilState.prototype, "isDirty", {
+                get: function () {
+                    return this._isStencilTestDirty || this._isStencilMaskDirty || this._isStencilFuncDirty || this._isStencilOpDirty;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilFunc", {
+                get: function () {
+                    return this._stencilFunc;
+                },
+                set: function (value) {
+                    if (this._stencilFunc === value) {
+                        return;
+                    }
+                    this._stencilFunc = value;
+                    this._isStencilFuncDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilFuncRef", {
+                get: function () {
+                    return this._stencilFuncRef;
+                },
+                set: function (value) {
+                    if (this._stencilFuncRef === value) {
+                        return;
+                    }
+                    this._stencilFuncRef = value;
+                    this._isStencilFuncDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilFuncMask", {
+                get: function () {
+                    return this._stencilFuncMask;
+                },
+                set: function (value) {
+                    if (this._stencilFuncMask === value) {
+                        return;
+                    }
+                    this._stencilFuncMask = value;
+                    this._isStencilFuncDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilOpStencilFail", {
+                get: function () {
+                    return this._stencilOpStencilFail;
+                },
+                set: function (value) {
+                    if (this._stencilOpStencilFail === value) {
+                        return;
+                    }
+                    this._stencilOpStencilFail = value;
+                    this._isStencilOpDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilOpDepthFail", {
+                get: function () {
+                    return this._stencilOpDepthFail;
+                },
+                set: function (value) {
+                    if (this._stencilOpDepthFail === value) {
+                        return;
+                    }
+                    this._stencilOpDepthFail = value;
+                    this._isStencilOpDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilOpStencilDepthPass", {
+                get: function () {
+                    return this._stencilOpStencilDepthPass;
+                },
+                set: function (value) {
+                    if (this._stencilOpStencilDepthPass === value) {
+                        return;
+                    }
+                    this._stencilOpStencilDepthPass = value;
+                    this._isStencilOpDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilMask", {
+                get: function () {
+                    return this._stencilMask;
+                },
+                set: function (value) {
+                    if (this._stencilMask === value) {
+                        return;
+                    }
+                    this._stencilMask = value;
+                    this._isStencilMaskDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(_StencilState.prototype, "stencilTest", {
+                get: function () {
+                    return this._stencilTest;
+                },
+                set: function (value) {
+                    if (this._stencilTest === value) {
+                        return;
+                    }
+                    this._stencilTest = value;
+                    this._isStencilTestDirty = true;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            _StencilState.prototype.reset = function () {
+                this._stencilTest = false;
+                this._stencilMask = 0xFF;
+                this._stencilFunc = WebGLRenderingContext.ALWAYS;
+                this._stencilFuncRef = 1;
+                this._stencilFuncMask = 0xFF;
+                this._stencilOpStencilFail = WebGLRenderingContext.KEEP;
+                this._stencilOpDepthFail = WebGLRenderingContext.KEEP;
+                this._stencilOpStencilDepthPass = WebGLRenderingContext.REPLACE;
+                this._isStencilTestDirty = true;
+                this._isStencilMaskDirty = true;
+                this._isStencilFuncDirty = true;
+                this._isStencilOpDirty = true;
+            };
+            _StencilState.prototype.apply = function (gl) {
+                if (!this.isDirty) {
+                    return;
+                }
+                // Stencil test
+                if (this._isStencilTestDirty) {
+                    if (this.stencilTest) {
+                        gl.enable(gl.STENCIL_TEST);
+                    }
+                    else {
+                        gl.disable(gl.STENCIL_TEST);
+                    }
+                    this._isStencilTestDirty = false;
+                }
+                // Stencil mask
+                if (this._isStencilMaskDirty) {
+                    gl.stencilMask(this.stencilMask);
+                    this._isStencilMaskDirty = false;
+                }
+                // Stencil func
+                if (this._isStencilFuncDirty) {
+                    gl.stencilFunc(this.stencilFunc, this.stencilFuncRef, this.stencilFuncMask);
+                    this._isStencilFuncDirty = false;
+                }
+                // Stencil op
+                if (this._isStencilOpDirty) {
+                    gl.stencilOp(this.stencilOpStencilFail, this.stencilOpDepthFail, this.stencilOpStencilDepthPass);
+                    this._isStencilOpDirty = false;
+                }
+            };
+            return _StencilState;
+        }());
+        Internals._StencilState = _StencilState;
+    })(Internals = BABYLON.Internals || (BABYLON.Internals = {}));
+})(BABYLON || (BABYLON = {}));

+ 7 - 1
src/babylon.engine.ts

@@ -327,6 +327,7 @@
         private _caps: EngineCapabilities;
         private _pointerLockRequested: boolean;
         private _alphaTest: boolean;
+        private _isStencilEnable: boolean; 
 
         private _loadingScreen: ILoadingScreen;
 
@@ -381,7 +382,7 @@
 
         private _externalData: StringDictionary<Object>;
         private _bindedRenderFunction: any;
-
+        
         /**
          * @constructor
          * @param {HTMLCanvasElement} canvas - the canvas to be used for rendering
@@ -446,6 +447,7 @@
             this.resize();
 
             // Caps
+            this._isStencilEnable = options.stencil;
             this._caps = new EngineCapabilities();
             this._caps.maxTexturesImageUnits = this._gl.getParameter(this._gl.MAX_TEXTURE_IMAGE_UNITS);
             this._caps.maxTextureSize = this._gl.getParameter(this._gl.MAX_TEXTURE_SIZE);
@@ -556,6 +558,10 @@
             return this._webGLVersion;
         }
 
+        public get isStencilEnable(): boolean {
+            return this._isStencilEnable;
+        }
+
         private _prepareWorkingCanvas(): void {
             if (this._workingCanvas) {
                 return;

+ 2 - 2
src/babylon.scene.ts

@@ -2933,8 +2933,8 @@
                 transparentSortCompareFn);
         }
 
-        public setRenderingAutoClear(renderingGroupId: number, autoClear: boolean) {            
-            this._renderingManager.setRenderingAutoClear(renderingGroupId, autoClear);
+        public setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClear: boolean) {            
+            this._renderingManager.setRenderingAutoClearDepthStencil(renderingGroupId, autoClear);
         }
     }
 }