浏览代码

Add Metallic Workflow

sevan 8 年之前
父节点
当前提交
702721c884
共有 4 个文件被更改,包括 126 次插入45 次删除
  1. 1 1
      localDev/index.html
  2. 63 15
      src/Materials/babylon.pbrMaterial.ts
  3. 60 27
      src/Shaders/pbr.fragment.fx
  4. 2 2
      src/Shaders/pbr.vertex.fx

+ 1 - 1
localDev/index.html

@@ -59,7 +59,7 @@
 			.require(indexjs)
 			.require(indexjs)
 			.load(function() {
 			.load(function() {
 				if (BABYLON.Engine.isSupported()) {
 				if (BABYLON.Engine.isSupported()) {
-					engine = new BABYLON.Engine(canvas, true);				
+					engine = new BABYLON.Engine(canvas, true, { stencil: true });				
 
 
 					// call the scene creation from the js.
 					// call the scene creation from the js.
 					var scene = createScene();
 					var scene = createScene();

+ 63 - 15
src/Materials/babylon.pbrMaterial.ts

@@ -64,6 +64,10 @@
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPX = false;
         public INVERTNORMALMAPY = false;
         public INVERTNORMALMAPY = false;
         public SHADOWFULLFLOAT = false;
         public SHADOWFULLFLOAT = false;
+        
+        public METALLICWORKFLOW = false;
+        public METALLICROUGHNESSGSTOREINALPHA = false;
+        public METALLICROUGHNESSGSTOREINGREEN = false;
 
 
         constructor() {
         constructor() {
             super();
             super();
@@ -282,6 +286,12 @@
         @serializeAsTexture()
         @serializeAsTexture()
         public reflectivityTexture: BaseTexture;
         public reflectivityTexture: BaseTexture;
 
 
+        /**
+         * Used to switch from specular/glossiness to metallic/roughness workflow.
+         */
+        @serializeAsTexture()
+        public metallicTexture: BaseTexture;
+
         @serializeAsTexture()
         @serializeAsTexture()
         public bumpTexture: BaseTexture;
         public bumpTexture: BaseTexture;
 
 
@@ -313,12 +323,11 @@
         public emissiveColor = new Color3(0, 0, 0);
         public emissiveColor = new Color3(0, 0, 0);
         
         
         /**
         /**
-
          * AKA Glossiness in other nomenclature.
          * AKA Glossiness in other nomenclature.
          */
          */
         @serialize()
         @serialize()
         public microSurface = 0.9;
         public microSurface = 0.9;
-        
+
         /**
         /**
          * source material index of refraction (IOR)' / 'destination material IOR.
          * source material index of refraction (IOR)' / 'destination material IOR.
          */
          */
@@ -378,6 +387,18 @@
          */
          */
         @serialize()
         @serialize()
         public useMicroSurfaceFromReflectivityMapAlpha = false;
         public useMicroSurfaceFromReflectivityMapAlpha = false;
+
+        /**
+         * Specifies if the metallic texture contains the roughness information in its alpha channel.
+         */
+        @serialize()
+        public useRoughnessFromMetallicTextureAlpha = true;
+
+        /**
+         * Specifies if the metallic texture contains the roughness information in its green channel.
+         */
+        @serialize()
+        public useRoughnessFromMetallicTextureGreen = false;
         
         
         /**
         /**
          * In case the reflectivity map does not contain the microsurface information in its alpha channel,
          * In case the reflectivity map does not contain the microsurface information in its alpha channel,
@@ -725,14 +746,26 @@
                     }
                     }
                 }
                 }
 
 
-                if (this.reflectivityTexture && StandardMaterial.SpecularTextureEnabled) {
-                    if (!this.reflectivityTexture.isReady()) {
-                        return false;
-                    } else {
-                        needUVs = true;
-                        this._defines.REFLECTIVITY = true;
-                        this._defines.MICROSURFACEFROMREFLECTIVITYMAP = this.useMicroSurfaceFromReflectivityMapAlpha;
-                        this._defines.MICROSURFACEAUTOMATIC = this.useAutoMicroSurfaceFromReflectivityMap;
+                if (StandardMaterial.SpecularTextureEnabled) {                        
+                    if (this.metallicTexture) {
+                        if (!this.metallicTexture.isReady()) {
+                            return false;
+                        } else {
+                            needUVs = true;
+                            this._defines.METALLICWORKFLOW = true;
+                            this._defines.METALLICROUGHNESSGSTOREINALPHA = this.useRoughnessFromMetallicTextureAlpha;
+                            this._defines.METALLICROUGHNESSGSTOREINGREEN = !this.useRoughnessFromMetallicTextureAlpha && this.useRoughnessFromMetallicTextureGreen;
+                        }
+                    }
+                    else if (this.reflectivityTexture) {
+                        if (!this.reflectivityTexture.isReady()) {
+                            return false;
+                        } else {
+                            needUVs = true;
+                            this._defines.REFLECTIVITY = true;
+                            this._defines.MICROSURFACEFROMREFLECTIVITYMAP = this.useMicroSurfaceFromReflectivityMapAlpha;
+                            this._defines.MICROSURFACEAUTOMATIC = this.useAutoMicroSurfaceFromReflectivityMap;
+                        }
                     }
                     }
                 }
                 }
 
 
@@ -1174,11 +1207,19 @@
                         this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
                         this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
                     }
                     }
 
 
-                    if (this.reflectivityTexture && StandardMaterial.SpecularTextureEnabled) {
-                        this._effect.setTexture("reflectivitySampler", this.reflectivityTexture);
+                    if (StandardMaterial.SpecularTextureEnabled) {
+                        if (this.metallicTexture) {
+                            this._effect.setTexture("reflectivitySampler", this.metallicTexture);
+
+                            this._effect.setFloat2("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.metallicTexture.level);
+                            this._effect.setMatrix("reflectivityMatrix", this.metallicTexture.getTextureMatrix());
+                        }
+                        else if (this.reflectivityTexture) {
+                            this._effect.setTexture("reflectivitySampler", this.reflectivityTexture);
 
 
-                        this._effect.setFloat2("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level);
-                        this._effect.setMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
+                            this._effect.setFloat2("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level);
+                            this._effect.setMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
+                        }
                     }
                     }
 
 
                     if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
                     if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
@@ -1331,7 +1372,10 @@
                 results.push(this.emissiveTexture);
                 results.push(this.emissiveTexture);
             }
             }
 
 
-            if (this.reflectivityTexture && this.reflectivityTexture.animations && this.reflectivityTexture.animations.length > 0) {
+            if (this.metallicTexture && this.metallicTexture.animations && this.metallicTexture.animations.length > 0) {
+                results.push(this.metallicTexture);
+            }
+            else if (this.reflectivityTexture && this.reflectivityTexture.animations && this.reflectivityTexture.animations.length > 0) {
                 results.push(this.reflectivityTexture);
                 results.push(this.reflectivityTexture);
             }
             }
 
 
@@ -1376,6 +1420,10 @@
                     this.emissiveTexture.dispose();
                     this.emissiveTexture.dispose();
                 }
                 }
 
 
+                if (this.metallicTexture) {
+                    this.metallicTexture.dispose();
+                }
+
                 if (this.reflectivityTexture) {
                 if (this.reflectivityTexture) {
                     this.reflectivityTexture.dispose();
                     this.reflectivityTexture.dispose();
                 }
                 }

+ 60 - 27
src/Shaders/pbr.fragment.fx

@@ -87,7 +87,7 @@ uniform vec2 vLightmapInfos;
 uniform sampler2D lightmapSampler;
 uniform sampler2D lightmapSampler;
 #endif
 #endif
 
 
-#if defined(REFLECTIVITY)
+#if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
 varying vec2 vReflectivityUV;
 uniform vec2 vReflectivityInfos;
 uniform vec2 vReflectivityInfos;
 uniform sampler2D reflectivitySampler;
 uniform sampler2D reflectivitySampler;
@@ -255,17 +255,49 @@ void main(void) {
 	surfaceReflectivityColor = surfaceReflectivityColorMap.rgb;
 	surfaceReflectivityColor = surfaceReflectivityColorMap.rgb;
 	surfaceReflectivityColor = toLinearSpace(surfaceReflectivityColor);
 	surfaceReflectivityColor = toLinearSpace(surfaceReflectivityColor);
 
 
-#ifdef OVERLOADEDVALUES
-	surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
-#endif
+	#ifdef OVERLOADEDVALUES
+		surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
+	#endif
 
 
-#ifdef MICROSURFACEFROMREFLECTIVITYMAP
-	microSurface = surfaceReflectivityColorMap.a;
-#else
-#ifdef MICROSURFACEAUTOMATIC
-	microSurface = computeDefaultMicroSurface(microSurface, surfaceReflectivityColor);
-#endif
+	#ifdef MICROSURFACEFROMREFLECTIVITYMAP
+		microSurface = surfaceReflectivityColorMap.a;
+	#else
+		#ifdef MICROSURFACEAUTOMATIC
+			microSurface = computeDefaultMicroSurface(microSurface, surfaceReflectivityColor);
+		#endif
+	#endif
 #endif
 #endif
+
+#ifdef METALLICWORKFLOW
+	vec4 surfaceMetallicColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset);
+
+	// No gamma space fro the metallic map in metallic workflow.
+	float metallic = surfaceMetallicColorMap.r; // Unity like base channel for metallness.
+
+	// Diffuse is used as the base of the reflectivity.
+	vec3 baseColor = surfaceAlbedo.rgb;
+
+	// Drop the surface diffuse by the 1.0 - metalness.
+	surfaceAlbedo.rgb *= (1.0 - metallic);
+	
+	// Default specular reflectance at normal incidence.
+	// 4% corresponds to index of refraction (IOR) of 1.50, approximately equal to glass.    
+	const vec3 DefaultSpecularReflectanceDielectric = vec3(0.04, 0.04, 0.04);
+
+	// Compute the converted reflectivity.
+	surfaceReflectivityColor = mix(DefaultSpecularReflectanceDielectric, baseColor, metallic);
+
+	#ifdef OVERLOADEDVALUES
+		surfaceReflectivityColor = mix(surfaceReflectivityColor, vOverloadedReflectivity, vOverloadedIntensity.z);
+	#endif
+
+	#ifdef METALLICROUGHNESSGSTOREINALPHA
+		microSurface = 1.0 - surfaceMetallicColorMap.a;
+	#else
+		#ifdef METALLICROUGHNESSGSTOREINGREEN
+			microSurface = 1.0 - surfaceMetallicColorMap.g;
+		#endif
+	#endif
 #endif
 #endif
 
 
 #ifdef OVERLOADEDVALUES
 #ifdef OVERLOADEDVALUES
@@ -488,30 +520,31 @@ void main(void) {
 
 
 	// Compute refractance
 	// Compute refractance
 	vec3 refractance = vec3(0.0, 0.0, 0.0);
 	vec3 refractance = vec3(0.0, 0.0, 0.0);
+
 #ifdef REFRACTION
 #ifdef REFRACTION
 	vec3 transmission = vec3(1.0, 1.0, 1.0);
 	vec3 transmission = vec3(1.0, 1.0, 1.0);
-#ifdef LINKREFRACTIONTOTRANSPARENCY
-	// Transmission based on alpha.
-	transmission *= (1.0 - alpha);
+	#ifdef LINKREFRACTIONTOTRANSPARENCY
+		// Transmission based on alpha.
+		transmission *= (1.0 - alpha);
 
 
-	// Tint the material with albedo.
-	// TODO. PBR Tinting.
-	vec3 mixedAlbedo = surfaceAlbedoContribution.rgb * surfaceAlbedo.rgb;
-	float maxChannel = max(max(mixedAlbedo.r, mixedAlbedo.g), mixedAlbedo.b);
-	vec3 tint = clamp(maxChannel * mixedAlbedo, 0.0, 1.0);
+		// Tint the material with albedo.
+		// TODO. PBR Tinting.
+		vec3 mixedAlbedo = surfaceAlbedoContribution.rgb * surfaceAlbedo.rgb;
+		float maxChannel = max(max(mixedAlbedo.r, mixedAlbedo.g), mixedAlbedo.b);
+		vec3 tint = clamp(maxChannel * mixedAlbedo, 0.0, 1.0);
 
 
-	// Decrease Albedo Contribution
-	surfaceAlbedoContribution *= alpha;
+		// Decrease Albedo Contribution
+		surfaceAlbedoContribution *= alpha;
 
 
-	// Decrease irradiance Contribution
-	environmentIrradiance *= alpha;
+		// Decrease irradiance Contribution
+		environmentIrradiance *= alpha;
 
 
-	// Tint reflectance
-	surfaceRefractionColor *= tint;
+		// Tint reflectance
+		surfaceRefractionColor *= tint;
 
 
-	// Put alpha back to 1;
-	alpha = 1.0;
-#endif
+		// Put alpha back to 1;
+		alpha = 1.0;
+	#endif
 
 
 	// Add Multiple internal bounces.
 	// Add Multiple internal bounces.
 	vec3 bounceSpecularEnvironmentReflectance = (2.0 * specularEnvironmentReflectance) / (1.0 + specularEnvironmentReflectance);
 	vec3 bounceSpecularEnvironmentReflectance = (2.0 * specularEnvironmentReflectance) / (1.0 + specularEnvironmentReflectance);

+ 2 - 2
src/Shaders/pbr.vertex.fx

@@ -53,7 +53,7 @@ uniform vec2 vLightmapInfos;
 uniform mat4 lightmapMatrix;
 uniform mat4 lightmapMatrix;
 #endif
 #endif
 
 
-#if defined(REFLECTIVITY)
+#if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
 varying vec2 vReflectivityUV;
 uniform vec2 vReflectivityInfos;
 uniform vec2 vReflectivityInfos;
 uniform mat4 reflectivityMatrix;
 uniform mat4 reflectivityMatrix;
@@ -178,7 +178,7 @@ void main(void) {
     }
     }
 #endif
 #endif
 
 
-#if defined(REFLECTIVITY)
+#if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
     if (vReflectivityInfos.x == 0.)
     if (vReflectivityInfos.x == 0.)
     {
     {
         vReflectivityUV = vec2(reflectivityMatrix * vec4(uv, 1.0, 0.0));
         vReflectivityUV = vec2(reflectivityMatrix * vec4(uv, 1.0, 0.0));