瀏覽代碼

Merge pull request #991 from nockawa/master

Added Parallax Mapping in StandardMaterial
David Catuhe 9 年之前
父節點
當前提交
9513c49085

+ 2 - 1
materialsLibrary/materials/pbr/pbr.fragment.fx

@@ -797,7 +797,8 @@ void main(void) {
 
 
     #ifdef BUMP
-        normalW = perturbNormal(viewDirectionW);
+		mat3 TBN = cotangent_frame(vNormalW * vBumpInfos.y, -viewDirectionW, vBumpUV);
+		normalW = perturbNormal(viewDirectionW, TBN, vBumpUV);
     #endif
 
     // Ambient color

文件差異過大導致無法顯示
+ 857 - 830
src/Materials/babylon.standardMaterial.js


+ 32 - 2
src/Materials/babylon.standardMaterial.ts

@@ -8,6 +8,8 @@
         public EMISSIVE = false;
         public SPECULAR = false;
         public BUMP = false;
+        public PARALLAX = false;
+        public PARALLAXOCCLUSION = false;
         public SPECULAROVERALPHA = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
@@ -155,6 +157,15 @@
         public disableLighting = false;
 
         @serialize()
+        public useParallax = false;
+
+        @serialize()
+        public useParallaxOcclusion = false;
+
+        @serialize()
+        public parallaxScaleBias = 0.05;
+
+        @serialize()
         public roughness = 0;
 
         @serialize()
@@ -398,6 +409,13 @@
                     } else {
                         needUVs = true;
                         this._defines.BUMP = true;
+
+                        if (this.useParallax) {
+                            this._defines.PARALLAX = true;
+                            if (this.useParallaxOcclusion) {
+                                this._defines.PARALLAXOCCLUSION = true;
+                            }
+                        }
                     }
                 }
 
@@ -544,6 +562,14 @@
                     fallbacks.addFallback(0, "BUMP");
                 }
 
+                if (this._defines.PARALLAX) {
+                    fallbacks.addFallback(1, "PARALLAX");
+                }
+
+                if (this._defines.PARALLAXOCCLUSION) {
+                    fallbacks.addFallback(0, "PARALLAXOCCLUSION");
+                }
+
                 if (this._defines.SPECULAROVERALPHA) {
                     fallbacks.addFallback(0, "SPECULAROVERALPHA");
                 }
@@ -622,7 +648,7 @@
                         "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
                         "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
                         "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vLightmapInfos", "vRefractionInfos",
+                        "vDiffuseInfos", "vAmbientInfos", "vOpacityInfos", "vReflectionInfos", "vEmissiveInfos", "vSpecularInfos", "vBumpInfos", "vParallaxScaleBias", "vLightmapInfos", "vRefractionInfos",
                         "mBones",
                         "vClipPlane", "diffuseMatrix", "ambientMatrix", "opacityMatrix", "reflectionMatrix", "emissiveMatrix", "specularMatrix", "bumpMatrix", "lightmapMatrix", "refractionMatrix",
                         "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues",
@@ -766,8 +792,12 @@
                     if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled) {
                         this._effect.setTexture("bumpSampler", this.bumpTexture);
 
-                        this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level);
+                        this._effect.setFloat3("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level, this.parallaxScaleBias);
                         this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
+
+                        if (this.useParallax) {
+                            this._effect.setFloat("vParallaxScaleBias", this.parallaxScaleBias);
+                        }
                     }
 
                     if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {

+ 70 - 5
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -1,6 +1,6 @@
 #ifdef BUMP
 	varying vec2 vBumpUV;
-	uniform vec2 vBumpInfos;
+	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
 
 	// Thanks to http://www.thetenthplanet.de/archives/1180
@@ -23,11 +23,76 @@
 		return mat3(tangent * invmax, binormal * invmax, normal);
 	}
 
-	vec3 perturbNormal(vec3 viewDir)
+	vec3 perturbNormal(vec3 viewDir, mat3 cotangentFrame, vec2 uv)
 	{
-		vec3 map = texture2D(bumpSampler, vBumpUV).xyz;
+		vec3 map = texture2D(bumpSampler, uv).xyz;
 		map = map * 255. / 127. - 128. / 127.;
-		mat3 TBN = cotangent_frame(vNormalW * vBumpInfos.y, -viewDir, vBumpUV);
-		return normalize(TBN * map);
+		return normalize(cotangentFrame * map);
 	}
+
+#ifdef PARALLAX
+	const float minSamples = 4.;
+	const float maxSamples = 15.;
+	const int iMaxSamples = 15;
+
+	// http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
+	vec2 parallaxOcclusion(vec3 vViewDirCoT, vec3 vNormalCoT, vec2 texCoord, float parallaxScale) {
+
+		float parallaxLimit = length(vViewDirCoT.xy) / vViewDirCoT.z;
+		parallaxLimit *= parallaxScale;
+		vec2 vOffsetDir = normalize(vViewDirCoT.xy);
+		vec2 vMaxOffset = vOffsetDir * parallaxLimit;
+		float numSamples = maxSamples + (dot(vViewDirCoT, vNormalCoT) * (minSamples - maxSamples));
+		float stepSize = 1.0 / numSamples;
+
+		// Uncomment whevener GL_EXT_shader_texture_lod with texture2DGradEXT will work
+		//vec2 dx = dFdx(vBumpUV);
+		//vec2 dy = dFdy(vBumpUV);
+
+		// Initialize the starting view ray height and the texture offsets.
+		float currRayHeight = 1.0;
+		vec2 vCurrOffset = vec2(0, 0);
+		vec2 vLastOffset = vec2(0, 0);
+
+		float lastSampledHeight = 1.0;
+		float currSampledHeight = 1.0;
+
+		for (int i = 0; i < iMaxSamples; i++)
+		{
+			currSampledHeight = texture2D(bumpSampler, vBumpUV + vCurrOffset).w;
+
+			// Test if the view ray has intersected the surface.
+			if (currSampledHeight > currRayHeight)
+			{
+				float delta1 = currSampledHeight - currRayHeight;
+				float delta2 = (currRayHeight + stepSize) - lastSampledHeight;
+				float ratio = delta1 / (delta1 + delta2);
+				vCurrOffset = (ratio)* vLastOffset + (1.0 - ratio) * vCurrOffset;
+
+				// Force the exit of the loop
+				break;
+			}
+			else
+			{
+				currRayHeight -= stepSize;
+				vLastOffset = vCurrOffset;
+				vCurrOffset += stepSize * vMaxOffset;
+
+				lastSampledHeight = currSampledHeight;
+			}
+		}
+
+		return vCurrOffset;
+	}
+
+	vec2 parallaxOffset(vec3 viewDir, float heightScale)
+	{
+		// calculate amount of offset for Parallax Mapping With Offset Limiting
+		float height = texture2D(bumpSampler, vBumpUV).w;
+		vec2 texCoordOffset = heightScale * viewDir.xy * height;
+		return -texCoordOffset;
+	}
+
+#endif
+
 #endif

+ 14 - 0
src/Shaders/ShadersInclude/helperFunctions.fx

@@ -0,0 +1,14 @@
+
+mat3 transposeMat3(mat3 inMatrix) {
+	vec3 i0 = inMatrix[0];
+	vec3 i1 = inMatrix[1];
+	vec3 i2 = inMatrix[2];
+
+	mat3 outMatrix = mat3(
+		vec3(i0.x, i1.x, i2.x),
+		vec3(i0.y, i1.y, i2.y),
+		vec3(i0.z, i1.z, i2.z)
+		);
+
+	return outMatrix;
+}

+ 53 - 14
src/Shaders/default.fragment.fx

@@ -1,4 +1,8 @@
-#ifdef BUMP
+#ifdef PARALLAX
+//#extension GL_EXT_shader_texture_lod : enable		// Doesn't work right now with texture2DGradExt...
+#endif
+
+#ifdef BUMP
 #extension GL_OES_standard_derivatives : enable
 #endif
 
@@ -30,6 +34,9 @@ varying vec3 vNormalW;
 varying vec4 vColor;
 #endif
 
+// Helper functions
+#include<helperFunctions>
+
 // Lights
 #include<light0FragmentDeclaration>
 #include<light1FragmentDeclaration>
@@ -161,8 +168,52 @@ void main(void) {
 	// Alpha
 	float alpha = vDiffuseColor.a;
 
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+#ifdef DIFFUSE
+	vec2 diffuseUV = vDiffuseUV;
+#endif
+
+#ifdef BUMP
+	vec2 bumpUV = vBumpUV;
+#endif
+
+#if defined(BUMP) || defined(PARALLAX)
+	mat3 TBN = cotangent_frame(normalW * vBumpInfos.y, -viewDirectionW, bumpUV);
+#endif
+
+#ifdef PARALLAX
+	mat3 invTBN = transposeMat3(TBN);
+
+#ifdef PARALLAXOCCLUSION
+	vec2 uvOffset = parallaxOcclusion(invTBN * -viewDirectionW, invTBN * normalW, bumpUV, vBumpInfos.z);
+#else
+	vec2 uvOffset = parallaxOffset(invTBN * viewDirectionW, vBumpInfos.z);
+#endif
+
+	diffuseUV += uvOffset;
+	bumpUV += uvOffset;
+
+	// Note by Loic: won't be nice with wrapping textures...
+#ifdef PARALLAXOCCLUSION
+	if (diffuseUV.x > 1.0 || diffuseUV.y > 1.0 || diffuseUV.x < 0.0 || diffuseUV.y < 0.0) {
+		discard;
+	}
+#endif
+
+#endif
+
+#ifdef BUMP
+	normalW = perturbNormal(viewDirectionW, TBN, bumpUV);
+#endif
+
 #ifdef DIFFUSE
-	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+	baseColor = texture2D(diffuseSampler, diffuseUV);
 
 #ifdef ALPHATEST
 	if (baseColor.a < 0.4)
@@ -180,18 +231,6 @@ void main(void) {
 	baseColor.rgb *= vColor.rgb;
 #endif
 
-	// Bump
-#ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
-#else
-	vec3 normalW = vec3(1.0, 1.0, 1.0);
-#endif
-
-
-#ifdef BUMP
-	normalW = perturbNormal(viewDirectionW);
-#endif
-
 	// Ambient color
 	vec3 baseAmbientColor = vec3(1., 1., 1.);
 

+ 1 - 1
src/Shaders/default.vertex.fx

@@ -61,7 +61,7 @@ uniform mat4 specularMatrix;
 
 #ifdef BUMP
 varying vec2 vBumpUV;
-uniform vec2 vBumpInfos;
+uniform vec3 vBumpInfos;
 uniform mat4 bumpMatrix;
 #endif