فهرست منبع

Fix vertex alpha for glTF loader
- Move transparencyMode from pbrBaseSimpleMaterial to pbrBaseMaterial
- Added Material.needAlphaBlendingForMesh() to decide whether blending should happen instead of renderGroup deciding based on mesh directly

Gary Hsu 7 سال پیش
والد
کامیت
0715162389

+ 6 - 1
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -323,6 +323,7 @@ module BABYLON.GLTF2 {
             }
             }
 
 
             node.babylonMesh = new Mesh(node.name || "mesh" + node.index, this._babylonScene);
             node.babylonMesh = new Mesh(node.name || "mesh" + node.index, this._babylonScene);
+            node.babylonMesh.hasVertexAlpha = true;
 
 
             this._loadTransform(node);
             this._loadTransform(node);
 
 
@@ -1383,10 +1384,12 @@ module BABYLON.GLTF2 {
             const alphaMode = material.alphaMode || "OPAQUE";
             const alphaMode = material.alphaMode || "OPAQUE";
             switch (alphaMode) {
             switch (alphaMode) {
                 case "OPAQUE": {
                 case "OPAQUE": {
-                    // default is opaque
+                    babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
                     break;
                     break;
                 }
                 }
                 case "MASK": {
                 case "MASK": {
+                    babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHATEST;
+
                     babylonMaterial.alphaCutOff = (material.alphaCutoff == null ? 0.5 : material.alphaCutoff);
                     babylonMaterial.alphaCutOff = (material.alphaCutoff == null ? 0.5 : material.alphaCutoff);
 
 
                     if (colorFactor) {
                     if (colorFactor) {
@@ -1404,6 +1407,8 @@ module BABYLON.GLTF2 {
                     break;
                     break;
                 }
                 }
                 case "BLEND": {
                 case "BLEND": {
+                    babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_ALPHABLEND;
+
                     if (colorFactor) {
                     if (colorFactor) {
                         babylonMaterial.alpha = colorFactor[3];
                         babylonMaterial.alpha = colorFactor[3];
                     }
                     }

+ 63 - 7
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -269,7 +269,7 @@
         protected _useLightmapAsShadowmap = false;
         protected _useLightmapAsShadowmap = false;
         
         
         /**
         /**
-         * Specifies that the alpha is coming form the albedo channel alpha channel.
+         * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending.
          */
          */
         protected _useAlphaFromAlbedoTexture = false;
         protected _useAlphaFromAlbedoTexture = false;
         
         
@@ -385,6 +385,11 @@
         protected _useAlphaFresnel = false;
         protected _useAlphaFresnel = false;
 
 
         /**
         /**
+         * The transparency mode of the material.
+         */
+        protected _transparencyMode: Nullable<number> = null;
+
+        /**
          * Specifies the environment BRDF texture used to comput the scale and offset roughness values
          * Specifies the environment BRDF texture used to comput the scale and offset roughness values
          * from cos thetav and roughness: 
          * from cos thetav and roughness: 
          * http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
          * http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
@@ -487,13 +492,60 @@
             this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
             this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
         }
         }
 
 
+        /**
+         * Gets the current transparency mode.
+         */
+        @serialize()
+        public get transparencyMode(): Nullable<number> {
+            return this._transparencyMode;
+        }
+
+        /**
+         * Sets the transparency mode of the material.
+         */
+        public set transparencyMode(value: Nullable<number>) {
+            if (this._transparencyMode === value) {
+                return;
+            }
+
+            this._transparencyMode = value;
+
+            this._forceAlphaTest = (value === PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND);
+
+            this._markAllSubMeshesAsTexturesDirty();
+        }
+
+        /**
+         * Specifies whether or not the meshes using this material should be rendered in alpha blend mode.
+         */
         public needAlphaBlending(): boolean {
         public needAlphaBlending(): boolean {
+            if (this._transparencyMode === PBRMaterial.PBRMATERIAL_OPAQUE ||
+                this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHATEST) {
+                return false;
+            }
+
+            return super.needAlphaBlending();
+        }
+
+        /**
+         * Specifies whether or not the meshes using this material should be rendered in alpha blend mode.
+         */
+        public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
             if (this._linkRefractionWithTransparency) {
             if (this._linkRefractionWithTransparency) {
                 return false;
                 return false;
             }
             }
-            return (this.alpha < 1.0) || (this._opacityTexture != null) || this._shouldUseAlphaFromAlbedoTexture();
+
+            if (this._transparencyMode === PBRMaterial.PBRMATERIAL_OPAQUE ||
+                this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHATEST) {
+                return false;
+            }
+
+            return super.needAlphaBlendingForMesh(mesh) || (this._opacityTexture != null) || this._shouldUseAlphaFromAlbedoTexture();
         }
         }
 
 
+        /**
+         * Specifies whether or not the meshes using this material should be rendered in alpha test mode.
+         */
         public needAlphaTesting(): boolean {
         public needAlphaTesting(): boolean {
             if (this._forceAlphaTest) {
             if (this._forceAlphaTest) {
                 return true;
                 return true;
@@ -502,11 +554,15 @@
             if (this._linkRefractionWithTransparency) {
             if (this._linkRefractionWithTransparency) {
                 return false;
                 return false;
             }
             }
-            return this._albedoTexture != null && this._albedoTexture.hasAlpha;
+
+            return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHATEST;
         }
         }
 
 
+        /**
+         * Specifies whether or not the alpha value of the albedo texture should be used for alpha blending.
+         */
         protected _shouldUseAlphaFromAlbedoTexture(): boolean {
         protected _shouldUseAlphaFromAlbedoTexture(): boolean {
-            return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture;
+            return this._albedoTexture != null && this._albedoTexture.hasAlpha && this._useAlphaFromAlbedoTexture && this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE;
         }
         }
 
 
         public getAlphaTestTexture(): BaseTexture {
         public getAlphaTestTexture(): BaseTexture {
@@ -797,7 +853,7 @@
 
 
                 defines.ALPHATESTVALUE = this._alphaCutOff;
                 defines.ALPHATESTVALUE = this._alphaCutOff;
                 defines.PREMULTIPLYALPHA = (this.alphaMode === Engine.ALPHA_PREMULTIPLIED || this.alphaMode === Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
                 defines.PREMULTIPLYALPHA = (this.alphaMode === Engine.ALPHA_PREMULTIPLIED || this.alphaMode === Engine.ALPHA_PREMULTIPLIED_PORTERDUFF);
-                defines.ALPHABLEND = this.needAlphaBlending();
+                defines.ALPHABLEND = this.needAlphaBlendingForMesh(mesh);
                 defines.ALPHAFRESNEL = this._useAlphaFresnel;
                 defines.ALPHAFRESNEL = this._useAlphaFresnel;
             }
             }
 
 
@@ -817,8 +873,8 @@
             // Values that need to be evaluated on every frame
             // Values that need to be evaluated on every frame
             MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
             MaterialHelper.PrepareDefinesForFrameBoundValues(scene, engine, defines, useInstances ? true : false, this._forceAlphaTest);
 
 
-             // Attribs
-            if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true)) {
+            // Attribs
+            if (MaterialHelper.PrepareDefinesForAttributes(mesh, defines, true, true, true, this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE)) {
                 if (mesh) {
                 if (mesh) {
                     if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                     if (!scene.getEngine().getCaps().standardDerivatives && !mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
                         mesh.createNormals(true);
                         mesh.createNormals(true);

+ 3 - 60
src/Materials/PBR/babylon.pbrBaseSimpleMaterial.ts

@@ -84,32 +84,6 @@
         @expandToProperty("_markAllSubMeshesAsTexturesDirty", "_alphaCutOff")
         @expandToProperty("_markAllSubMeshesAsTexturesDirty", "_alphaCutOff")
         public alphaCutOff: number;
         public alphaCutOff: number;
 
 
-        protected _transparencyMode: number = PBRMaterial.PBRMATERIAL_OPAQUE;
-        /**
-         * Gets the current transparency mode.
-         */
-        @serialize()
-        public get transparencyMode(): number {
-            return this._transparencyMode;
-        }
-        /**
-         * Sets the transparency mode of the material.
-         */
-        public set transparencyMode(value: number) {
-            if (this._transparencyMode === value) {
-                return;
-            }
-            this._transparencyMode = value;
-            if (value === PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND) {
-                this._forceAlphaTest = true;
-            }
-            else {
-                this._forceAlphaTest = false;
-            }
-            
-            this._markAllSubMeshesAsTexturesDirty();
-        }
-
         /**
         /**
          * Gets the current double sided mode.
          * Gets the current double sided mode.
          */
          */
@@ -130,39 +104,6 @@
         }
         }
 
 
         /**
         /**
-         * Specifies wether or not the alpha value of the albedo texture should be used.
-         */
-        protected _shouldUseAlphaFromAlbedoTexture(): boolean {
-            return this._albedoTexture && this._albedoTexture.hasAlpha && this._transparencyMode !== PBRMaterial.PBRMATERIAL_OPAQUE;
-        }
-
-        /**
-         * Specifies wether or not the meshes using this material should be rendered in alpha blend mode.
-         */
-        public needAlphaBlending(): boolean {
-            if (this._linkRefractionWithTransparency) {
-                return false;
-            }
-
-            return (this.alpha < 1.0) || 
-                    (this._shouldUseAlphaFromAlbedoTexture() &&
-                        (this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHABLEND ||
-                            this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND));
-        }
-
-        /**
-         * Specifies wether or not the meshes using this material should be rendered in alpha test mode.
-         */
-        public needAlphaTesting(): boolean {
-            if (this._linkRefractionWithTransparency) {
-                return false;
-            }
-
-            return this._shouldUseAlphaFromAlbedoTexture() &&
-                 this._transparencyMode === PBRMaterial.PBRMATERIAL_ALPHATEST;
-        }
-
-        /**
          * Return the active textures of the material.
          * Return the active textures of the material.
          */
          */
         public getActiveTextures(): BaseTexture[] {
         public getActiveTextures(): BaseTexture[] {
@@ -196,11 +137,13 @@
         constructor(name: string, scene: Scene) {
         constructor(name: string, scene: Scene) {
             super(name, scene);
             super(name, scene);
 
 
+            this._transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
+            this._useAlphaFromAlbedoTexture = true;
             this._useAmbientInGrayScale = true;
             this._useAmbientInGrayScale = true;
         }
         }
 
 
         public getClassName(): string {
         public getClassName(): string {
             return "PBRBaseSimpleMaterial";
             return "PBRBaseSimpleMaterial";
-        }        
+        }
     }
     }
 }
 }

+ 1 - 1
src/Materials/PBR/babylon.pbrMaterial.ts

@@ -222,7 +222,7 @@
         public useLightmapAsShadowmap = false;
         public useLightmapAsShadowmap = false;
         
         
         /**
         /**
-         * Specifies that the alpha is coming form the albedo channel alpha channel.
+         * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending.
          */
          */
         @serialize()
         @serialize()
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")

+ 4 - 0
src/Materials/babylon.material.ts

@@ -450,6 +450,10 @@
             return (this.alpha < 1.0);
             return (this.alpha < 1.0);
         }
         }
 
 
+        public needAlphaBlendingForMesh(mesh: AbstractMesh): boolean {
+            return (mesh.visibility < 1.0) || mesh.hasVertexAlpha;
+        }
+
         public needAlphaTesting(): boolean {
         public needAlphaTesting(): boolean {
             return false;
             return false;
         }
         }

+ 6 - 5
src/Materials/babylon.materialHelper.ts

@@ -69,10 +69,10 @@
             }
             }
         }
         }
 
 
-        public static PrepareDefinesForAttributes(mesh: AbstractMesh, defines: any, useVertexColor: boolean, useBones: boolean, useMorphTargets = false): boolean {
+        public static PrepareDefinesForAttributes(mesh: AbstractMesh, defines: any, useVertexColor: boolean, useBones: boolean, useMorphTargets = false, useVertexAlpha = true): boolean {
             if (!defines._areAttributesDirty && defines._needNormals === defines._normals && defines._needUVs === defines._uvs) {
             if (!defines._areAttributesDirty && defines._needNormals === defines._normals && defines._needUVs === defines._uvs) {
                 return false;
                 return false;
-            }               
+            }
 
 
             defines._normals = defines._needNormals;
             defines._normals = defines._needNormals;
             defines._uvs = defines._needUVs;
             defines._uvs = defines._needUVs;
@@ -92,8 +92,9 @@
             }
             }
 
 
             if (useVertexColor) {
             if (useVertexColor) {
-                defines["VERTEXCOLOR"] = mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind);
-                defines["VERTEXALPHA"] = mesh.hasVertexAlpha;
+                var hasVertexColors = mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind);
+                defines["VERTEXCOLOR"] = hasVertexColors;
+                defines["VERTEXALPHA"] = mesh.hasVertexAlpha && hasVertexColors && useVertexAlpha;
             }
             }
 
 
             if (useBones) {
             if (useBones) {
@@ -103,7 +104,7 @@
                 } else {
                 } else {
                     defines["NUM_BONE_INFLUENCERS"] = 0;
                     defines["NUM_BONE_INFLUENCERS"] = 0;
                     defines["BonesPerMesh"] = 0;
                     defines["BonesPerMesh"] = 0;
-                }           
+                }
             }
             }
 
 
             if (useMorphTargets) {
             if (useMorphTargets) {

+ 1 - 1
src/Rendering/babylon.renderingGroup.ts

@@ -324,7 +324,7 @@
                 return;
                 return;
             }
             }
 
 
-            if (material.needAlphaBlending() || mesh.visibility < 1.0 || mesh.hasVertexAlpha) { // Transparent
+            if (material.needAlphaBlending() || material.needAlphaBlendingForMesh(mesh)) { // Transparent
                 this._transparentSubMeshes.push(subMesh);
                 this._transparentSubMeshes.push(subMesh);
             } else if (material.needAlphaTesting()) { // Alpha test
             } else if (material.needAlphaTesting()) { // Alpha test
                 if (material.needDepthPrePass) {
                 if (material.needDepthPrePass) {