Explorar o código

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe %!s(int64=6) %!d(string=hai) anos
pai
achega
f0a52d0cef

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

@@ -127,6 +127,7 @@
 - onActiveCameraChanged shouldn't be fired when rendering rig cameras ([TrevorDev](https://github.com/TrevorDev))
 - Added `MeshExploder` class ([danjpar](https://github.com/danjpar))
 - Observables can now make observers top or bottom priority ([TrevorDev](https://github.com/TrevorDev))
+- Mesh outline no longer is shown through the mesh when it's transparent ([TrevorDev](https://github.com/TrevorDev))
 
 ### OBJ Loader
 - Add color vertex support (not part of standard) ([brianzinn](https://github.com/brianzinn))

+ 34 - 0
src/Engines/engine.ts

@@ -1771,6 +1771,40 @@ export class Engine {
         this._depthCullingState.depthFunc = this._gl.LESS;
     }
 
+    private _cachedStencilBuffer: boolean;
+    private _cachedStencilFunction: number;
+    private _cachedStencilMask: number;
+    private _cachedStencilOperationPass: number;
+    private _cachedStencilOperationFail: number;
+    private _cachedStencilOperationDepthFail: number;
+    private _cachedStencilReference: number;
+
+    /**
+     * Caches the the state of the stencil buffer
+     */
+    public cacheStencilState() {
+        this._cachedStencilBuffer = this.getStencilBuffer();
+        this._cachedStencilFunction = this.getStencilFunction();
+        this._cachedStencilMask = this.getStencilMask();
+        this._cachedStencilOperationPass = this.getStencilOperationPass();
+        this._cachedStencilOperationFail = this.getStencilOperationFail();
+        this._cachedStencilOperationDepthFail = this.getStencilOperationDepthFail();
+        this._cachedStencilReference = this.getStencilFunctionReference();
+    }
+
+    /**
+     * Restores the state of the stencil buffer
+     */
+    public restoreStencilState() {
+        this.setStencilFunction(this._cachedStencilFunction);
+        this.setStencilMask(this._cachedStencilMask);
+        this.setStencilBuffer(this._cachedStencilBuffer);
+        this.setStencilOperationPass(this._cachedStencilOperationPass);
+        this.setStencilOperationFail(this._cachedStencilOperationFail);
+        this.setStencilOperationDepthFail(this._cachedStencilOperationDepthFail);
+        this.setStencilFunctionReference(this._cachedStencilReference);
+    }
+
     /**
      * Sets the current depth function to LEQUAL
      */

+ 2 - 14
src/Layers/highlightLayer.ts

@@ -456,13 +456,7 @@ export class HighlightLayer extends EffectLayer {
 
         // Cache
         var engine = this._engine;
-        var previousStencilBuffer = engine.getStencilBuffer();
-        var previousStencilFunction = engine.getStencilFunction();
-        var previousStencilMask = engine.getStencilMask();
-        var previousStencilOperationPass = engine.getStencilOperationPass();
-        var previousStencilOperationFail = engine.getStencilOperationFail();
-        var previousStencilOperationDepthFail = engine.getStencilOperationDepthFail();
-        var previousStencilReference = engine.getStencilFunctionReference();
+        engine.cacheStencilState();
 
         // Stencil operations
         engine.setStencilOperationPass(Constants.REPLACE);
@@ -487,13 +481,7 @@ export class HighlightLayer extends EffectLayer {
         }
 
         // Restore Cache
-        engine.setStencilFunction(previousStencilFunction);
-        engine.setStencilMask(previousStencilMask);
-        engine.setStencilBuffer(previousStencilBuffer);
-        engine.setStencilOperationPass(previousStencilOperationPass);
-        engine.setStencilOperationFail(previousStencilOperationFail);
-        engine.setStencilOperationDepthFail(previousStencilOperationDepthFail);
-        engine.setStencilFunctionReference(previousStencilReference);
+        engine.restoreStencilState();
     }
 
     /**

+ 27 - 0
src/Rendering/outlineRenderer.ts

@@ -92,6 +92,10 @@ Object.defineProperty(AbstractMesh.prototype, "renderOverlay", {
  */
 export class OutlineRenderer implements ISceneComponent {
     /**
+     * Stencil value used to avoid outline being seen within the mesh when the mesh is transparent
+     */
+    private static _StencilReference = 0x04;
+    /**
      * The name of the component. Each component must have a unique name.
      */
     public name = SceneComponentConstants.NAME_OUTLINERENDERER;
@@ -274,9 +278,32 @@ export class OutlineRenderer implements ISceneComponent {
         // Outline - step 1
         this._savedDepthWrite = this._engine.getDepthWrite();
         if (mesh.renderOutline) {
+            var material = subMesh.getMaterial();
+            if (material && material.needAlphaBlending) {
+                this._engine.cacheStencilState();
+                // Draw only to stencil buffer for the original mesh
+                // The resulting stencil buffer will be used so the outline is not visible inside the mesh when the mesh is transparent
+                this._engine.setDepthWrite(false);
+                this._engine.setColorWrite(false);
+                this._engine.setStencilBuffer(true);
+                this._engine.setStencilOperationPass(Constants.REPLACE);
+                this._engine.setStencilFunction(Constants.ALWAYS);
+                this._engine.setStencilMask(OutlineRenderer._StencilReference);
+                this._engine.setStencilFunctionReference(OutlineRenderer._StencilReference);
+                this.render(subMesh, batch, /* This sets offset to 0 */ true);
+
+                this._engine.setColorWrite(true);
+                this._engine.setStencilFunction(Constants.NOTEQUAL);
+            }
+
+            // Draw the outline using the above stencil if needed to avoid drawing within the mesh
             this._engine.setDepthWrite(false);
             this.render(subMesh, batch);
             this._engine.setDepthWrite(this._savedDepthWrite);
+
+            if (material && material.needAlphaBlending) {
+                this._engine.restoreStencilState();
+            }
         }
     }