ソースを参照

waterMaterial supports logarithmic depth ! separate fresnel color blending

- logarithmic depth support
- correcting uwrap/vwrap bug in rendertargets, causing weird artifacts
at the sides of the screen
- superinposing smaller bump waves for more dynamic waves
- separate refraction/reflection color blending with physically correct
(nonlinear) fresnel calculation
László Matuska 9 年 前
コミット
8083139b80

+ 81 - 7
materialsLibrary/materials/water/babylon.waterMaterial.ts

@@ -18,6 +18,11 @@ module BABYLON {
         public BonesPerMesh = 0;
         public INSTANCES = false;
         public SPECULARTERM = false;
+        public LOGARITHMICDEPTH = false;
+        public FRESNELSEPARATE = false;
+        public BUMPSUPERIMPOSE = false;
+        public BUMPAFFECTSREFLECTION = false;
+
 
         constructor() {
             super();
@@ -68,7 +73,23 @@ module BABYLON {
         @serialize()
 		public bumpHeight: number = 0.4;
         /**
-        * @param {number}: The water color blended with the reflection and refraction samplers
+         * @param {boolean}: Add a smaller moving bump to less steady waves.
+         */
+        @serialize()
+        public bumpSuperimpose = false;
+        /**
+         * @param {boolean}: Color refraction and reflection differently with .waterColor2 and .colorBlendFactor2. Non-linear (physically correct) fresnel.
+         */
+        @serialize()
+        public fresnelSeparate = false;
+        /**
+         * @param {boolean}: bump Waves modify the reflection.
+         */
+        @serialize()
+        public bumpAffectsReflection = false;
+
+        /**
+        * @param {number}: The water color blended with the refraction (near)
         */
         @serializeAsColor3()
 		public waterColor: Color3 = new Color3(0.1, 0.1, 0.6);
@@ -78,6 +99,16 @@ module BABYLON {
         @serialize()
 		public colorBlendFactor: number = 0.2;
         /**
+         * @param {number}: The water color blended with the reflection (far)
+         */
+        @serializeAsColor3()
+        public waterColor2: Color3 = new Color3(0.1, 0.1, 0.6);
+        /**
+         * @param {number}: The blend factor related to the water color (reflection, far)
+         */
+        @serialize()
+        public colorBlendFactor2: number = 0.2;
+        /**
         * @param {number}: Represents the maximum length of a wave
         */
         @serialize()
@@ -106,8 +137,10 @@ module BABYLON {
 
         private _defines = new WaterMaterialDefines();
         private _cachedDefines = new WaterMaterialDefines();
-		
-		/**
+
+        private _useLogarithmicDepth: boolean;
+
+        /**
 		* Constructor
 		*/
 		constructor(name: string, scene: Scene, public renderTargetSize: Vector2 = new Vector2(512, 512)) {
@@ -116,7 +149,16 @@ module BABYLON {
 			// Create render targets
 			this._createRenderTargets(scene, renderTargetSize);
         }
-		
+
+        @serialize()
+        public get useLogarithmicDepth(): boolean {
+            return this._useLogarithmicDepth;
+        }
+
+        public set useLogarithmicDepth(value: boolean) {
+            this._useLogarithmicDepth = value && this.getScene().getEngine().getCaps().fragmentDepthSupported;
+        }
+
         // Get / Set
         public get refractionTexture(): RenderTargetTexture {
             return this._refractionRTT;
@@ -228,6 +270,22 @@ module BABYLON {
                 this._defines.POINTSIZE = true;
             }
 
+            if (this.useLogarithmicDepth) {
+                this._defines.LOGARITHMICDEPTH = true;
+            }
+
+            if (this.fresnelSeparate) {
+                this._defines.FRESNELSEPARATE = true;
+            }
+
+            if (this.bumpSuperimpose) {
+                this._defines.BUMPSUPERIMPOSE = true;
+            }
+
+            if (this.bumpAffectsReflection) {
+                this._defines.BUMPAFFECTSREFLECTION = true;
+            }
+
             // Fog
             if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
                 this._defines.FOG = true;
@@ -284,6 +342,10 @@ module BABYLON {
                     fallbacks.addFallback(1, "FOG");
                 }
 
+                if (this._defines.LOGARITHMICDEPTH) {
+                    fallbacks.addFallback(0, "LOGARITHMICDEPTH");
+                }
+
                 MaterialHelper.HandleFallbacksForShadows(this._defines, fallbacks, this.maxSimultaneousLights);
              
                 if (this._defines.NUM_BONE_INFLUENCERS > 0) {
@@ -320,9 +382,11 @@ module BABYLON {
                     "vNormalInfos", 
                     "mBones",
                     "vClipPlane", "normalMatrix",
+                    "logarithmicDepthConstant",
+
                     // Water
                     "worldReflectionViewProjection", "windDirection", "waveLength", "time", "windForce",
-                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "colorBlendFactor", "waveSpeed"
+                    "cameraPosition", "bumpHeight", "waveHeight", "waterColor", "waterColor2", "colorBlendFactor", "colorBlendFactor2", "waveSpeed"
                 ]
                 var samplers = ["normalSampler",
                     // Water
@@ -403,7 +467,10 @@ module BABYLON {
 
             // Fog
             MaterialHelper.BindFogParameters(scene, mesh, this._effect);
-            
+
+            // Log. depth
+            MaterialHelper.BindLogDepth(this._defines, this._effect, scene);
+
             // Water
             if (StandardMaterial.ReflectionTextureEnabled) {
                 this._effect.setTexture("refractionSampler", this._refractionRTT);
@@ -422,6 +489,8 @@ module BABYLON {
             this._effect.setFloat("bumpHeight", this.bumpHeight);
 			this._effect.setColor4("waterColor", this.waterColor, 1.0);
 			this._effect.setFloat("colorBlendFactor", this.colorBlendFactor);
+            this._effect.setColor4("waterColor2", this.waterColor2, 1.0);
+            this._effect.setFloat("colorBlendFactor2", this.colorBlendFactor2);
             this._effect.setFloat("waveSpeed", this.waveSpeed);
 
             super.bind(world, mesh);
@@ -430,8 +499,13 @@ module BABYLON {
 		private _createRenderTargets(scene: Scene, renderTargetSize: Vector2): void {
 			// Render targets
 			this._refractionRTT = new RenderTargetTexture(name + "_refraction", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
+            this._refractionRTT.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
+            this._refractionRTT.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
+
 			this._reflectionRTT = new RenderTargetTexture(name + "_reflection", {width: renderTargetSize.x, height: renderTargetSize.y}, scene, false, true);
-			
+            this._reflectionRTT.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
+            this._reflectionRTT.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
+
 			scene.customRenderTargets.push(this._refractionRTT);
 			scene.customRenderTargets.push(this._reflectionRTT);
 			

+ 127 - 45
materialsLibrary/materials/water/water.fragment.fx

@@ -1,3 +1,7 @@
+#ifdef LOGARITHMICDEPTH
+#extension GL_EXT_frag_depth : enable
+#endif
+
 precision highp float;
 
 // Constants
@@ -28,6 +32,7 @@ varying vec4 vColor;
 // Samplers
 #ifdef BUMP
 varying vec2 vNormalUV;
+varying vec2 vNormalUV2;
 uniform sampler2D normalSampler;
 uniform vec2 vNormalInfos;
 #endif
@@ -43,14 +48,20 @@ uniform vec3 cameraPosition;
 uniform vec4 waterColor;
 uniform float colorBlendFactor;
 
+uniform vec4 waterColor2;
+uniform float colorBlendFactor2;
+
 uniform float bumpHeight;
 
+uniform float time;
+
 // Water varyings
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 varying vec3 vPosition;
 
 #include<clipPlaneFragmentDeclaration>
+#include<logDepthDeclaration>
 
 // Fog
 #include<fogFragmentDeclaration>
@@ -69,7 +80,11 @@ void main(void) {
 	float alpha = vDiffuseColor.a;
 
 #ifdef BUMP
-	baseColor = texture2D(normalSampler, vNormalUV);
+    #ifdef BUMPSUPERIMPOSE
+    	baseColor = 0.6 * texture2D(normalSampler, vNormalUV) + 0.4 * texture2D(normalSampler,vec2(vNormalUV2.x,vNormalUV2.y));
+    #else
+	    baseColor = texture2D(normalSampler, vNormalUV);
+    #endif
 	vec3 bumpColor = baseColor.rgb;
 
 #ifdef ALPHATEST
@@ -88,63 +103,130 @@ void main(void) {
 
 	// Bump
 #ifdef NORMAL
-	vec3 normalW = normalize(vNormalW);
 	vec2 perturbation = bumpHeight * (baseColor.rg - 0.5);
+	#ifdef BUMPAFFECTSREFLECTION
+	    vec3 normalW = normalize(vNormalW + vec3(perturbation.x*8.0,0.0,perturbation.y*8.0));
+	    if (normalW.y<0.0) {
+	        normalW.y = -normalW.y;
+	    }
+    #else
+    	vec3 normalW = normalize(vNormalW);
+	#endif
 #else
 	vec3 normalW = vec3(1.0, 1.0, 1.0);
 	vec2 perturbation = bumpHeight * (vec2(1.0, 1.0) - 0.5);
 #endif
 
-#ifdef REFLECTION
-	// Water
-	vec3 eyeVector = normalize(vEyePosition - vPosition);
-	
-	vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation, 0.0, 1.0);
-	vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
-	
-	vec2 projectedReflectionTexCoords = clamp(vReflectionMapTexCoord.xy / vReflectionMapTexCoord.z + perturbation, 0.0, 1.0);
-	vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
-	
-	vec3 upVector = vec3(0.0, 1.0, 0.0);
-	
-	float fresnelTerm = max(dot(eyeVector, upVector), 0.0);
-	
-	vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * (1.0 - fresnelTerm);
-	
-	baseColor = colorBlendFactor * waterColor + (1.0 - colorBlendFactor) * combinedColor;
-#endif
+#ifdef FRESNELSEPARATE
+    #ifdef REFLECTION
+        // Water
+        vec3 eyeVector = normalize(vEyePosition - vPosition);
+
+        vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation*0.5, 0.0, 1.0);
+        vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
 
-	// Lighting
-	vec3 diffuseBase = vec3(0., 0., 0.);
+        vec2 projectedReflectionTexCoords = clamp(vec2(
+            vReflectionMapTexCoord.x / vReflectionMapTexCoord.z + perturbation.x * 0.3,
+            vReflectionMapTexCoord.y / vReflectionMapTexCoord.z + perturbation.y
+        ),0.0, 1.0);
+
+        vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
+
+        vec3 upVector = vec3(0.0, 1.0, 0.0);
+
+        float fresnelTerm = clamp(abs(pow(dot(eyeVector, upVector),3.0)),0.05,0.65);
+        float IfresnelTerm = 1.0 - fresnelTerm;
+
+        refractiveColor = colorBlendFactor*waterColor + (1.0-colorBlendFactor)*refractiveColor;
+        reflectiveColor = IfresnelTerm*colorBlendFactor2*waterColor + (1.0-colorBlendFactor2*IfresnelTerm)*reflectiveColor;
+
+        vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * IfresnelTerm;
+        baseColor = combinedColor;
+    #endif
+
+    // Lighting
+    vec3 diffuseBase = vec3(0., 0., 0.);
     lightingInfo info;
-	float shadow = 1.;
-    
-#ifdef SPECULARTERM
-	float glossiness = vSpecularColor.a;
-	vec3 specularBase = vec3(0., 0., 0.);
-    vec3 specularColor = vSpecularColor.rgb;
-#else
-	float glossiness = 0.;
-#endif
-    
-#include<lightFragment>[0..maxSimultaneousLights]
+    float shadow = 1.;
 
-#ifdef VERTEXALPHA
-	alpha *= vColor.a;
-#endif
+    #ifdef SPECULARTERM
+        float glossiness = vSpecularColor.a;
+        vec3 specularBase = vec3(0., 0., 0.);
+        vec3 specularColor = vSpecularColor.rgb;
+    #else
+        float glossiness = 0.;
+    #endif
 
-#ifdef SPECULARTERM
-	vec3 finalSpecular = specularBase * specularColor;
-#else
-	vec3 finalSpecular = vec3(0.0);
-#endif
+    #include<lightFragment>[0..maxSimultaneousLights]
+
+    vec3 finalDiffuse = clamp(baseColor.rgb, 0.0, 1.0);
+
+    #ifdef VERTEXALPHA
+        alpha *= vColor.a;
+    #endif
+
+    #ifdef SPECULARTERM
+        vec3 finalSpecular = specularBase * specularColor;
+    #else
+        vec3 finalSpecular = vec3(0.0);
+    #endif
+
+
+#else // !FRESNELSEPARATE
+    #ifdef REFLECTION
+        // Water
+        vec3 eyeVector = normalize(vEyePosition - vPosition);
+
+        vec2 projectedRefractionTexCoords = clamp(vRefractionMapTexCoord.xy / vRefractionMapTexCoord.z + perturbation, 0.0, 1.0);
+        vec4 refractiveColor = texture2D(refractionSampler, projectedRefractionTexCoords);
+
+        vec2 projectedReflectionTexCoords = clamp(vReflectionMapTexCoord.xy / vReflectionMapTexCoord.z + perturbation, 0.0, 1.0);
+        vec4 reflectiveColor = texture2D(reflectionSampler, projectedReflectionTexCoords);
+
+        vec3 upVector = vec3(0.0, 1.0, 0.0);
+
+        float fresnelTerm = max(dot(eyeVector, upVector), 0.0);
 
-	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
+        vec4 combinedColor = refractiveColor * fresnelTerm + reflectiveColor * (1.0 - fresnelTerm);
+
+        baseColor = colorBlendFactor * waterColor + (1.0 - colorBlendFactor) * combinedColor;
+    #endif
+
+    // Lighting
+    vec3 diffuseBase = vec3(0., 0., 0.);
+    lightingInfo info;
+    float shadow = 1.;
+
+    #ifdef SPECULARTERM
+        float glossiness = vSpecularColor.a;
+        vec3 specularBase = vec3(0., 0., 0.);
+        vec3 specularColor = vSpecularColor.rgb;
+    #else
+        float glossiness = 0.;
+    #endif
+
+    #include<lightFragment>[0..maxSimultaneousLights]
+
+    vec3 finalDiffuse = clamp(baseColor.rgb, 0.0, 1.0);
+
+
+    #ifdef VERTEXALPHA
+        alpha *= vColor.a;
+    #endif
+
+    #ifdef SPECULARTERM
+        vec3 finalSpecular = specularBase * specularColor;
+    #else
+        vec3 finalSpecular = vec3(0.0);
+    #endif
+
+#endif
 
-	// Composition
-	vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
+// Composition
+vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
 
+#include<logDepthFragment>
 #include<fogFragment>
 	
 	gl_FragColor = color;
-}
+}

+ 17 - 1
materialsLibrary/materials/water/water.vertex.fx

@@ -25,6 +25,9 @@ uniform mat4 viewProjection;
 
 #ifdef BUMP
 varying vec2 vNormalUV;
+#ifdef BUMPSUPERIMPOSE
+    varying vec2 vNormalUV2;
+#endif
 uniform mat4 normalMatrix;
 uniform vec2 vNormalInfos;
 #endif
@@ -48,6 +51,8 @@ varying vec4 vColor;
 #include<fogVertexDeclaration>
 #include<shadowsVertexDeclaration>[0..maxSimultaneousLights]
 
+#include<logDepthDeclaration>
+
 // Water uniforms
 uniform mat4 worldReflectionViewProjection;
 uniform vec2 windDirection;
@@ -62,6 +67,8 @@ varying vec3 vPosition;
 varying vec3 vRefractionMapTexCoord;
 varying vec3 vReflectionMapTexCoord;
 
+
+
 void main(void) {
 
     #include<instancesVertex>
@@ -86,10 +93,16 @@ void main(void) {
 	if (vNormalInfos.x == 0.)
 	{
 		vNormalUV = vec2(normalMatrix * vec4((uv * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+        #ifdef BUMPSUPERIMPOSE
+		    vNormalUV2 = vec2(normalMatrix * vec4((uv * 0.721) / waveLength + time * 1.2 * windForce * windDirection, 1.0, 0.0));
+		#endif
 	}
 	else
 	{
-		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection, 1.0, 0.0));
+		vNormalUV = vec2(normalMatrix * vec4((uv2 * 1.0) / waveLength + time * windForce * windDirection , 1.0, 0.0));
+        #ifdef BUMPSUPERIMPOSE
+    		vNormalUV2 = vec2(normalMatrix * vec4((uv2 * 0.721) / waveLength + time * 1.2 * windForce * windDirection , 1.0, 0.0));
+    	#endif
 	}
 #endif
 
@@ -134,4 +147,7 @@ void main(void) {
 	vReflectionMapTexCoord.y = 0.5 * (worldPos.w + worldPos.y);
 	vReflectionMapTexCoord.z = worldPos.w;
 #endif
+
+#include<logDepthVertex>
+
 }