Newer
Older
Shader "Unlit/WaterShader"
_DeepColor("Deep Color", Color) = (1,1,1,1)
_ShallowColor("Shallow Color", Color) = (1,1,1,1)
_ShallowThreshold("Shallow Threshold", Range(0,5)) = 0.5
_ShallowTint("Shallow Tint", Range(0,1)) = 0.5
_FoamColor("Foam Color", Color) = (1,1,1,1)
_FoamTex("Foam Texture", 2D) = "white" {}
_FoamSpeed("Foam Speed", Vector) = (0.005, 0.02, -0.04 ,0.07)
_FoamThreshold("Foam Threshold", Range(0,5)) = 0.5
_FoamHardness("Foam Hardness", Range(0,25)) = 0.5
_CausticsTex("Caustics Texture", 2D) = "white" {}
_CausticsSpeed("Caustics Speed", Vector) = (0.005, 0.02, -0.04 ,0.07)
_WaveSpeed("Wave Speed", Range(-5,5)) = 0.5
_WaveA("Wave A (dir, steepness, wavelength)", Vector) = (1,0,0.5,10)
_WaveB("Wave B", Vector) = (0,1,0.25,20)
_WaveC("Wave C", Vector) = (1,1,0.15,10)
_ReflectionStrength("Reflection Strength", Range(0,1)) = 0.5
_ReflectionDeform("Reflection Deform", Range(-1,1)) = 0.5
[HideInInspector]_ReflectionTex("Reflection", 2D) = "white" {}
SubShader
Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
LOD 100
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
GrabPass { "_UnderWater" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "GerstnerWave.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float3 normal : NORMAL;
fixed2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD2;
};
fixed4 _DeepColor, _ShallowColor, _FoamColor, _FoamSpeed, _CausticsSpeed, _WaveA, _WaveB, _WaveC;
sampler2D _CausticsTex, _FoamTex, _ReflectionTex, _CameraDepthTexture, _UnderWater, _CameraNormalsTexture;
float _WaveSpeed, _ShallowThreshold, _ShallowTint, _FoamThreshold, _ReflectionStrength, _ReflectionDeform, _FoamHardness;
float4 _CausticsTex_ST, _FoamTex_ST;
v2f vert (appdata_full v)
{
v2f o;
//Generate Waves
float3 gridPoint = v.vertex.xyz;
float3 tangent = 0;
float3 binormal = 0;
float3 p = gridPoint;
p += GerstnerWave(_WaveA, gridPoint, tangent, binormal, _WaveSpeed);
p += GerstnerWave(_WaveB, gridPoint, tangent, binormal, _WaveSpeed);
p += GerstnerWave(_WaveC, gridPoint, tangent, binormal, _WaveSpeed);
v.vertex.xyz = p;
o.normal = v.normal = normalize(cross(binormal, tangent));
o.vertex = UnityObjectToClipPos(v.vertex);
//Calculate screen position and pass to frag shader
o.screenPos = ComputeScreenPos(o.vertex);
o.uv = v.texcoord;
return o;
}
/// <summary>
/// Gets the distance that water must travel through the water at a given point to reach the eye
/// </summary>
float GetWaterDepth(float4 screenPos, float2 screenUV) {
float backgroundDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screenUV));
float surfaceDepth = UNITY_Z_0_FAR_FROM_CLIPSPACE(screenPos.z);
return backgroundDepth - surfaceDepth;
}
fixed4 frag(v2f i) : SV_Target
{
// Initialize the output color
fixed4 col = _DeepColor;
//Calculate screen space UV position
float2 screenUV = i.screenPos.xy / i.screenPos.w;
float depth = GetWaterDepth(i.screenPos, screenUV);
float3 existingNormal = tex2Dproj(_CameraNormalsTexture, UNITY_PROJ_COORD(i.screenPos));
float3 normalDot = saturate(dot(existingNormal, i.normal));
//Calculate water caustics
float2 caustUV1 = TRANSFORM_TEX(i.uv, _CausticsTex);
float2 caustUV2 = caustUV1;
caustUV1.xy = (caustUV1.xy + _CausticsSpeed.xy * _Time.y);
caustUV2.xy = (caustUV2.xy + _CausticsSpeed.zw * _Time.y);
fixed3 caustic1 = tex2D(_CausticsTex, caustUV1).rgb;
fixed3 caustic2 = tex2D(_CausticsTex, caustUV2).rgb;
fixed3 causticrgb = caustic1 * caustic2;
//Calculate water depth fog and foam
float fogRatio = saturate(depth * _ShallowThreshold);
col.xyz = tex2D(_UnderWater, screenUV).rgb * (1 - _ShallowTint);
col.xyz += _ShallowColor * _ShallowTint;
col.xyz *= (1 - fogRatio);
col.xyz += _DeepColor * fogRatio;
col.xyz += causticrgb;
//Deform the planar reflections based on surface normal
float4 reflectDeformed = i.screenPos;
reflectDeformed.xyz += i.normal.xyz * _ReflectionDeform;
//Add reflections
col.xyz *= 1 - _ReflectionStrength;
col.xyz += tex2Dproj(_ReflectionTex, reflectDeformed).rgb * _ReflectionStrength;
//add foam after reflections
float2 foamUV1 = TRANSFORM_TEX(i.uv, _FoamTex);
float2 foamUV2 = foamUV1 + _FoamSpeed.zw * _Time.y;
foamUV1.xy += _FoamSpeed.xy * _Time.y;
float foamAmt = 1 - saturate((depth - _FoamThreshold) * _FoamHardness);
foamAmt *= saturate(tex2D(_FoamTex, foamUV1).r * tex2D(_FoamTex, foamUV2).r * _FoamHardness);
col.xyz += _FoamColor * foamAmt;
clamp(col, 0, 1);
return col;
}
ENDCG