再谈water效果

先上效果图,一步一步拆解开:
(1)焦散
焦散效果
(2)水的颜色深浅的插值
在这里插入图片描述

(3)随着视角和相机的远近,会有一个圆圈的红色(这是自己设置的菲涅尔颜色,请留意一下)和xiangj

(4)反射水中的倒影和倒影的扰动
在这里插入图片描述
(5)岸边的处理
在这里插入图片描述
(6)泡沫的处理:由弱变强 变弱
在这里插入图片描述
(7)在焦散中用到 还原scene的世界坐标:
详细介绍在这还原世界坐标

在这里插入图片描述

(8)泡沫波浪的感觉:请添加图片描述

(9)水面的高度起伏变化:

在这里插入图片描述

(10) 总体的效果:
请添加图片描述

用到的知识点,之前的文章中都介绍过,如果不能理解代码的意图,请翻看前面的文章。


```csharp
Shader "Unlit/Water_Code"
{
	Properties
	{
		_ReflectionTex("_ReflectionTex",2D) = "white"{}


		_WaterNormal ("_WaterNormal", 2D) = "white" {}
		_NormalTilling("_NormalTilling",float) = 2.5
		_NoiseIntensity("_NoiseIntensity",float) = 3
		_WaterSpeed("_WaterSpeed",vector) = (-4,0,0,0)
		_WaterNoise("_WaterNoise",float) = 1


		_DeepthColor("_DeepthColor",color) = (1,1,1,1)
		_ShallowColor("_ShallowColor",color) = (1,1,1,1)
		_DeepRange("_DeepRange",float) = 1

		
		_FresnelColor("_FresnelColor",color) = (0,0,0,0)
		_FresnalPower("_FresnalPower",range(0,10)) = 5
		
		_ReflectDistort("_ReflectDistort",float) = 1
		_ReflectIntensity("_ReflectIntensity",range(0,2)) = 0.8
		_ReflectPower("_ReflectPower",range(0,10)) = 5

		/// 水下折射扰动强度
		_UnderWaterDistort("_UnderWaterDistort",range(0,2))= 1

		 焦散
		_CausticsTex("_CausticsTex",2D) = "white"{}
		_CausticsScale("_CausticsScale",float) = 8
		_CausticsSpeed("_CausticsSpeed",vector) = (-8,1,0,0)
		_CausticsIntensity("_CausticsIntensity",range(0,10)) = 3
		_CausticsRange("_CausticsRange",range(0,2)) = 1

		 岸边
		_ShoreColor("_ShoreColor",color) = (1.0,1.0,1.0,1.0)
		_ShoreRange("_ShoreRange",range(0,5)) = 1 
		_ShoreEdgeWidth("_ShoreEdgeWidth",range(0,1.0)) = 0.2
		_ShoreEdgeIntensity("_ShoreEdgeIntensity",float) = 0.2

		 泡沫
		_FoamColor("_FoamColor",color) = (1,1,1,1)
		_FoamRange("_FoamRange",float) = 1
		_FoamBlend("_FoamBlend",range(0,1.0)) = 0
		_FoamWidth("_FoamWidth",range(0,1)) = 0.15
		_FoamFrequency("_FoamFrequency",float) = 15
		_FoamSpeed("_FoamSpeed",float) = -1
		_FoamNoise("_FoamNoise",vector) = (10,40,0,0)
		_FoamDissolve("_FoamDissolve",range(0,1.5)) = 1.6

		 海浪的波形运动  (speedX,speedX,steepness,waveLength)
		_WaveA("_WaveA",vector) = (1,-1,1.6,50)
		_WaveB("_WaveB",vector) = (-0.5,-0.5,1.6,30)
		_WaveC("_WaveC",vector) = (1,0.5,1.6,20)



	}
	SubShader
	{
		Tags { "RenderType"="Transparent" "Queue"="Transparent" }
		LOD 100
	
		Grabpass{}

		Pass
		{
			ZWrite off
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "UnityStandardUtils.cginc"
			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 pos : SV_POSITION;
				float3 worldPos : TEXCOORD1;
				float3 worldTangent : TEXCOORD2;
				float3 worldBinormal : TEXCOORD3;
				float3 worldNormal : TEXCOORD4;
				float4 screenPos : TEXCOORD5;
				float4 GrabPos : TEXCOORD6;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float4 _DeepthColor,_ShallowColor;
			float _DeepRange;
			float4 _NormalSpeed;
			sampler2D_float _CameraDepthTexture;
			sampler2D _NormalMap,_ReflectionTex;
			float _NormalScale,_NormalNoise;
			float4 _FresnelColor;
			float _FresnalPower;
			float _ReflectDistort;
			float _ReflectPower,_ReflectIntensity;
			sampler2D _CausticsTex;
			float _CausticsScale,_CausticsRange;
			float4 _CausticsSpeed;
			float _CausticsIntensity;
			float _ShoreRange,_ShoreEdgeWidth,_ShoreEdgeIntensity;
			float4 _ShoreColor ,_FoamColor;

			sampler2D _GrabTexture;
			float _UnderWaterDistort;
			sampler2D _WaterNormal;
			float4 _WaterSpeed;
			float _WaterNoise,_NoiseIntensity,_NormalTilling;
			float _FoamRange,_FoamBlend,_FoamWidth,_FoamFrequency,_FoamSpeed,_FoamDissolve;

			float4 _FoamNoise;

			float4 _WaveA,_WaveB,_WaveC;

		float2 GradientNoiseDir( float2 x )
		{
			const float2 k = float2( 0.3183099, 0.3678794 );
			x = x * k + k.yx;
			return -1.0 + 2.0 * frac( 16.0 * k * frac( x.x * x.y * ( x.x + x.y ) ) );
		}
		
		float GradientNoise( float2 UV, float Scale )
		{
			float2 p = UV * Scale;
			float2 i = floor( p );
			float2 f = frac( p );
			float2 u = f * f * ( 3.0 - 2.0 * f );
			return lerp( lerp( dot( GradientNoiseDir( i + float2( 0.0, 0.0 ) ), f - float2( 0.0, 0.0 ) ),
					dot( GradientNoiseDir( i + float2( 1.0, 0.0 ) ), f - float2( 1.0, 0.0 ) ), u.x ),
					lerp( dot( GradientNoiseDir( i + float2( 0.0, 1.0 ) ), f - float2( 0.0, 1.0 ) ),
					dot( GradientNoiseDir( i + float2( 1.0, 1.0 ) ), f - float2( 1.0, 1.0 ) ), u.x ), u.y );
		}

			///  
			float3 GenerateWaveOffset(float3 worldPos,inout float3 tangent,inout float3 binormal,float4 wave)
			{
				float steepness = wave.z * 0.01;
				float waveLength = wave.w ;
				float k = 2 * UNITY_PI  / waveLength;
				float c = sqrt(9.8 / k);
				float2 d = normalize(wave.xy);
				float f = k * (dot(d,worldPos.xz) - c * _Time.y );
				float a = steepness / k;
				tangent += float3(-d.x * d.x * (steepness * sin(f)),  d.x * (steepness * cos(f)),-d.x * d.y * (steepness * sin(f)));
				binormal += float3(-d.x * d.y * (steepness * sin(f)),  d.y * (steepness * cos(f)),-d.y * d.y * (steepness * sin(f)));
				return float3(d.x * ( a * cos(f) ),a * sin(f),d.y * (a * cos(f)));
			}






			v2f vert (appdata v)
			{
				v2f o;
				  波形的顶点动画:
				float3 worldPos = mul(unity_ObjectToWorld,v.vertex);
				float3 tangent = float3(1,0,0);
				float3 binormal = float3(0,1,0);				
				float3 offset1 =  GenerateWaveOffset(worldPos,tangent,binormal,_WaveA);
				float3 offset2 =  GenerateWaveOffset(worldPos,tangent,binormal,_WaveB);
				float3 offset3 =  GenerateWaveOffset(worldPos,tangent,binormal,_WaveC);
				float3 endWorldPos = worldPos + (offset1 + offset2 + offset3);
				float3 objPos  = mul( unity_WorldToObject,float4(endWorldPos,1));
				v.vertex = float4(objPos.xyz,1.0);

				float3 endNormal = normalize(cross(tangent,binormal));
				endNormal = mul( unity_WorldToObject,float4(endNormal,0)).xyz;
				v.normal = endNormal;



				/ 
				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldPos = mul(unity_ObjectToWorld,v.vertex);
				o.worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
				o.worldTangent = normalize(UnityObjectToWorldNormal(v.tangent));
				o.worldBinormal =normalize(cross(o.worldTangent,o.worldNormal) * v.tangent.w);
				o.screenPos = ComputeScreenPos(o.pos);
				o.screenPos = ComputeGrabScreenPos(o.pos);
				o.uv = v.uv;
				COMPUTE_EYEDEPTH(o.screenPos.z);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{		

				/// 还原世界坐标
				float depth = tex2D(_CameraDepthTexture, i.screenPos.xy / i.screenPos.w).r;
				float secneZ = LinearEyeDepth(depth);
				float4 screenPos1 = float4(i.screenPos.xy /i.screenPos.w * 2.0 -1.0,0,-1);
				float3 viewVector = mul(unity_CameraInvProjection,screenPos1);
				float3 viewDir = normalize(mul(unity_CameraToWorld,viewVector));
				float3 rebuildWorldPos = _WorldSpaceCameraPos + viewDir * secneZ;
				//return float4(rebuildWorldPos,1.0);


				float3 worldPos = i.worldPos;
				float2 uv = worldPos.xz / _NormalTilling + (_Time.y * 0.1f * _WaterSpeed);
				float2 uv3 = worldPos.xz / _NormalTilling * 2.0f + (_Time.y * 0.1f * _WaterSpeed * -0.5);
				//float3 worldNormal = UnpackScaleNormal( tex2D(_WaterNormal,uv),_NoiseIntensity);						
				float3 worldNormal = UnpackNormal( tex2D(_WaterNormal,uv));						
				worldNormal.xy  *= _NoiseIntensity;
				worldNormal.z = sqrt(1.0 - dot(worldNormal.xy,worldNormal.xy));
				float3 worldNormal1 = UnpackNormal( tex2D(_WaterNormal,uv3));						
				worldNormal1 *= _NoiseIntensity;
				worldNormal1.z = sqrt(1.0 - dot(worldNormal1.xy,worldNormal1.xy));
				worldNormal += worldNormal1;
				worldNormal *= 0.5;
				worldNormal.z = sqrt(1.0 - dot(worldNormal.xy,worldNormal.xy));	
				float3 tangentNormal = worldNormal;			
				worldNormal = normalize(mul(float3x3(i.worldTangent,i.worldBinormal,i.worldNormal),worldNormal));
				//return float4(worldNormal.rgb,1.0);


				/// 求出深度差
				float sceneZ = LinearEyeDepth(tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD(i.screenPos)).r);
				float objZ = i.screenPos.z;
				float diff = abs(sceneZ - objZ);
				//return float4(diff.xxx,1.0);
				float3 worldView = normalize(UnityWorldSpaceViewDir(worldPos));
				/// 求出水的颜色 :  深水和浅水的 颜色插值   ; 水的颜色 和 水的折射的插值   
				float lerpFactor = saturate(exp(-diff / 5.0));
				float4 waterColor = lerp(_DeepthColor,_ShallowColor,lerpFactor);
				float fresnel =  0 + (1-0) * pow(max(dot(worldNormal,worldView),0.0001),_FresnalPower);
				waterColor = lerp(waterColor,_FresnelColor,fresnel);
				float waterOpacity = 1 - waterColor.a;
				//return float4(waterColor.rgb,1.0f);
			
				// 用菲涅尔 控制反射和折射的比率
				// 反射颜色 reflectColor   用切线空间下的法线扰动,是因为该空间下的法线可以反映顶点局部空间下的法线方向 是基于UV坐标轴的
				float2 screenPos = i.screenPos.xy / i.screenPos.w;
				float2 uv_Reflect = tangentNormal.xy * (_ReflectDistort * 0.01)	 + screenPos;	
				float4 reflectColor = tex2D(_ReflectionTex,uv_Reflect);
				
				float fresnel_Reflect = 0.0 + _ReflectIntensity * pow(max(dot(worldNormal,worldView),0.0001),_ReflectPower);
				reflectColor = reflectColor * fresnel_Reflect;
				//return float4(reflectColor.xyz,1.0);


				 
				float2 UV_grab = worldNormal.xz / (i.pos.w+1) * _UnderWaterDistort;
				float4 sceneColor = tex2D(_GrabTexture,i.GrabPos.xy / i.GrabPos.w + UV_grab);
				//return float4(sceneColor.rgb,1.0);



				
				//焦散 : 用还原的世界坐标中的 xz 值 采样焦散图
				float2 positionFromDepth = rebuildWorldPos.xz;
				float2 uv1 = (positionFromDepth / _CausticsScale) +  (_Time.y * _CausticsSpeed.xy * 0.01);
				float2 uv2 = -(positionFromDepth / _CausticsScale) +  (_Time.y * _CausticsSpeed.xy * 0.01);
				float4 causticsColor1 = tex2D(_CausticsTex,uv1);
				float4 causticsColor2 = tex2D(_CausticsTex,uv2);
				float4 causticsColor = min(causticsColor1,causticsColor2) * _CausticsIntensity;
				float causticsMask = saturate(exp(-diff / _CausticsRange));
				causticsColor = causticsColor * causticsMask;
				float4 underWaterColor = causticsColor + sceneColor;
				//return float4(underWaterColor.rgb,1.0); 
				
				
				 water shore  岸边的处理
				float waterShore = saturate(exp(-diff / _ShoreRange));
				float shoreEdge = smoothstep(1 - _ShoreEdgeWidth,1, waterShore) * _ShoreEdgeIntensity;
				float3 shoreColor = (_ShoreColor * sceneColor).rgb;
				//return float4(shoreColor.rgb,1.0);


				 Foam noise扰动
				float foamNoise =  GradientNoise(i.uv,_FoamNoise.xy);
				 Foam 泡沫的处理
				float foamSorce = saturate(diff / _FoamRange); 
				float foamMask = 1 - smoothstep(_FoamBlend,1.0,foamSorce + 0.1);
				float width = 1 - foamSorce - _FoamWidth;
				float sinResult = sin(((1- foamSorce) * _FoamFrequency) + (_Time.y * _FoamSpeed)); 
				//float4 foamColor = step(width,sinResult + foamNoise +  - _FoamDissolve) * foamMask * _FoamColor;
				float4 foamColor = step(width,sinResult + foamNoise +(1 - foamSorce)  - _FoamDissolve) * foamMask * _FoamColor;
				//return float4(foamColor.rgb,1.0);
				/// 最后的结果
				float4 waterFaceCOlor = lerp(reflectColor + waterColor, causticsColor, waterOpacity); 
				float3 faceColor = lerp(waterFaceCOlor.rgb,shoreColor,waterShore);
				//return float4(faceColor,1.0);
				float3 FaceColorWithFoam = lerp(faceColor,faceColor + foamColor.rgb,foamColor.a);
				//return float4(FaceColorWithFoam,1.0);
				float3 endColor = saturate(FaceColorWithFoam + shoreEdge);
				return float4(endColor.rgb,1.0);


			}
			ENDCG
		}
	}
}

之前的水:水效果

Guess you like

Origin blog.csdn.net/js0907/article/details/119812327