瀏覽代碼

Feature Complete

Sebastien Vandenberghe 8 年之前
父節點
當前提交
64462285c0
共有 3 個文件被更改,包括 84 次插入5 次删除
  1. 29 1
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  2. 13 0
      src/Shaders/ShadersInclude/pbrFunctions.fx
  3. 42 4
      src/Shaders/pbr.fragment.fx

+ 29 - 1
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -72,6 +72,7 @@
         public METALLNESSSTOREINMETALMAPBLUE = false;
         public AOSTOREINMETALMAPRED = false;
         public MICROSURFACEMAP = false;
+        public ENVIRONMENTBRDF = false;
 
         public MORPHTARGETS = false;
         public MORPHTARGETS_NORMAL = false;
@@ -364,6 +365,13 @@
         protected _useAlphaFresnel = false;
 
         /**
+         * Specifies the environment BRDF texture used to comput the scale and offset roughness values
+         * from cos thetav and roughness: 
+         * http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
+         */
+        protected _environmentBRDFTexture: BaseTexture = null;
+
+        /**
          * Default configuration related to image processing available in the PBR Material.
          */
         @serializeAsImageProcessingConfiguration()
@@ -700,6 +708,14 @@
                         }
                     }
 
+                    if (this._environmentBRDFTexture && StandardMaterial.ReflectionTextureEnabled) {
+                        // This is blocking.
+                        if (!this._environmentBRDFTexture.isReady()) {
+                            return false;
+                        }
+                        defines.ENVIRONMENTBRDF = true;
+                    }
+
                     if (this._shouldUseAlphaFromAlbedoTexture()) {
                         defines.ALPHAFROMALBEDO = true;
                     }
@@ -762,6 +778,10 @@
 
                 // Fallbacks
                 var fallbacks = new EffectFallbacks();
+                if (defines.ENVIRONMENTBRDF) {
+                    fallbacks.addFallback(0, "ENVIRONMENTBRDF");
+                }
+
                 if (defines.REFLECTION) {
                     fallbacks.addFallback(0, "REFLECTION");
                 }
@@ -856,7 +876,7 @@
                     "bumpSampler", "lightmapSampler", "opacitySampler",
                     "refractionSampler", "refractionSamplerLow", "refractionSamplerHigh",
                     "reflectionSampler", "reflectionSamplerLow", "reflectionSamplerHigh",
-                    "microSurfaceSampler", "brdfSampler"];
+                    "microSurfaceSampler", "environmentBrdfSampler"];
                 var uniformBuffers = ["Material", "Scene"];
 
                 ImageProcessingConfiguration.PrepareUniforms(uniforms, defines);
@@ -1134,6 +1154,10 @@
                         }
                     }
 
+                    if (defines.ENVIRONMENTBRDF) {
+                        this._uniformBuffer.setTexture("environmentBrdfSampler", this._environmentBRDFTexture);
+                    }
+
                     if (refractionTexture && StandardMaterial.RefractionTextureEnabled) {
                         if (defines.LODBASEDMICROSFURACE) {
                             this._uniformBuffer.setTexture("refractionSampler", refractionTexture);
@@ -1301,6 +1325,10 @@
                     this._reflectionTexture.dispose();
                 }
 
+                if (this._environmentBRDFTexture) {
+                    this._environmentBRDFTexture.dispose();
+                }
+
                 if (this._emissiveTexture) {
                     this._emissiveTexture.dispose();
                 }

+ 13 - 0
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -126,4 +126,17 @@ float getLodFromAlphaG(float cubeMapDimensionPixels, float alphaG, float NdotV)
     float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
     float lod = log2(microsurfaceAverageSlopeTexels);
     return lod;
+}
+
+float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) {
+    // Best balanced (implementation time vs result vs perf) analytical environment specular occlusion found.
+    // http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx
+    float temp = NdotVUnclamped + ambientOcclusion;
+    return clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0);
+}
+
+float environmentHorizonOcclusion(vec3 reflection, vec3 normal) {
+	// http://marmosetco.tumblr.com/post/81245981087
+    float temp = clamp( 1.0 + 0.3 * dot(reflection, normal), 0.0, 1.0);
+    return square(temp);
 }

+ 42 - 4
src/Shaders/pbr.fragment.fx

@@ -135,6 +135,10 @@ uniform sampler2D microSurfaceSampler;
 	#include<reflectionFunction>
 #endif
 
+#ifdef ENVIRONMENTBRDF
+	uniform sampler2D environmentBrdfSampler;
+#endif
+
 // Forces linear space for image processing
 #ifndef FROMLINEARSPACE
 	#define FROMLINEARSPACE;
@@ -172,10 +176,18 @@ void main(void) {
 	vec3 normalW = normalize(cross(dFdx(vPositionW), dFdy(vPositionW)));
 #endif
 
+#ifdef BUMP
+	vec3 originalNormalW = normalW;
+#endif
+
 #include<bumpFragment>
 
 #if defined(TWOSIDEDLIGHTING) && defined(NORMAL) 
 	normalW = gl_FrontFacing ? normalW : -normalW;
+
+	#ifdef BUMP
+		vec3 originalNormalW = gl_FrontFacing ? originalNormalW : -originalNormalW;;
+	#endif
 #endif
 
 // _____________________________ Albedo Information ______________________________
@@ -343,7 +355,8 @@ void main(void) {
 
 // _____________________________ Compute LODs Fetch ____________________________________
 	// Compute N dot V.
-	float NdotV = clamp(dot(normalW, viewDirectionW),0., 1.) + 0.00001;
+	float NdotVUnclamped = dot(normalW, viewDirectionW);
+	float NdotV = clamp(NdotVUnclamped,0., 1.) + 0.00001;
 	float alphaG = convertRoughnessToAverageSlope(roughness);
 
 // _____________________________ Refraction Info _______________________________________
@@ -503,9 +516,6 @@ void main(void) {
 	vec3 specularEnvironmentR0 = surfaceReflectivityColor.rgb;
 	vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
 
-	// Environment Reflectance
-	vec3 specularEnvironmentReflectance = fresnelSchlickEnvironmentGGX(clamp(NdotV, 0., 1.), specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface));
-
 // _____________________________ Direct Lighting Info __________________________________
 	vec3 diffuseBase = vec3(0., 0., 0.);
 #ifdef SPECULARTERM
@@ -522,6 +532,34 @@ void main(void) {
 
 #include<lightFragment>[0..maxSimultaneousLights]
 
+// _________________________ Specular Environment Oclusion __________________________
+#ifdef ENVIRONMENTBRDF
+	// Indexed on cos(theta) and roughness
+	vec2 brdfSamplerUV = vec2(NdotV, roughness);
+	// We can find the scale and offset to apply to the specular value.
+	vec2 environmentBrdf = texture2D(environmentBrdfSampler, brdfSamplerUV).xy;
+	vec3 specularEnvironmentReflectance = specularEnvironmentR0 * environmentBrdf.x + environmentBrdf.y;
+
+	#ifdef AMBIENTINGRAYSCALE
+		float ambientMonochrome = ambientOcclusionColor.r;
+	#else
+		float ambientMonochrome = getLuminance(ambientOcclusionColor);
+	#endif
+
+	vec3 seo = environmentRadianceOcclusion(ambientMonochrome, NdotVUnclamped);
+	specularEnvironmentReflectance *= seo;
+
+	#ifdef BUMP
+		#ifdef REFLECTIONMAP_3D
+			vec3 hoo = environmentHorizonOcclusion(reflectionCoords, normalW);
+			specularEnvironmentReflectance *= hoo;
+		#endif
+	#endif
+#else
+	// Jones implementation of a well balanced fast analytical solution.
+	vec3 specularEnvironmentReflectance = fresnelSchlickEnvironmentGGX(NdotV, specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface));
+#endif
+
 // _____________________________ Refractance+Tint ________________________________
 #ifdef REFRACTION
 	vec3 refractance = vec3(0.0, 0.0, 0.0);