Feautures:
Vertex displacement via supplied heightmap, Surface normals are recalculated for the displaced vertices.
Reflection via cubemap.
Color and normal texture with time based UV panning.
Shader "HeightMappedWater" { Properties { _Color ("Main Color", Color) = (1,1,1,1) _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "white" {} _BumpMap ("Normal (Normal)", 2D) = "bump" {} _HeightMap ("Heightmap (R)", 2D) = "grey" {} _HeightmapStrength ("Heightmap Strength", Float) = 1.0 _ExtrusionStrength ("Extrusion Strength", Float) = 1.0 _HeightmapDimX ("Heightmap Width", Float) = 2048 _HeightmapDimY ("Heightmap Height", Float) = 2048 _Cube ("Cubemap", CUBE) = "" {} _CubeStrength ("Reflective", Range(0.0,1.0)) = 0.5 _PanXSpeed ("UV Pan X Speed(-1.0 to 1.0)", Range(-1.0,1.0)) = 0.0 _PanYSpeed ("UV Pan Y Speed(-1.0 to 1.0)", Range(-1.0,1.0)) = 0.0 } SubShader{ Tags { "Queue" = "Transparent" } Blend SrcAlpha OneMinusSrcAlpha // Alpha blending BlendOp Add Cull Back CGPROGRAM #pragma surface surf NormalsHeight vertex:vert alpha #pragma target 3.0 struct Input { float2 uv_MainTex; float2 uv_HeightMap; float2 uv_BumpMap; float3 worldRefl; INTERNAL_DATA }; sampler2D _MainTex, _BumpMap, _HeightMap; float _HeightmapStrength, _HeightmapDimX, _HeightmapDimY,_ExtrusionStrength; float4 _Color; samplerCUBE _Cube; float _CubeStrength; float _PanXSpeed,_PanYSpeed; float2 pannedUV; void vert (inout appdata_full v) { float4 tex = tex2Dlod (_HeightMap, float4(v.texcoord.xy,0,0)); v.vertex.xyz += v.normal * (tex.rgb * _ExtrusionStrength); } void surf (Input IN, inout SurfaceOutput o) { pannedUV += fixed2(_PanXSpeed * _Time.y, _PanYSpeed * _Time.y); float3 normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap + pannedUV)); float me = tex2D(_HeightMap,IN.uv_MainTex).x; float n = tex2D(_HeightMap,float2(IN.uv_HeightMap.x,IN.uv_HeightMap.y+1.0/_HeightmapDimY)).x; float s = tex2D(_HeightMap,float2(IN.uv_HeightMap.x,IN.uv_HeightMap.y-1.0/_HeightmapDimY)).x; float e = tex2D(_HeightMap,float2(IN.uv_HeightMap.x-1.0/_HeightmapDimX,IN.uv_HeightMap.y)).x; float w = tex2D(_HeightMap,float2(IN.uv_HeightMap.x+1.0/_HeightmapDimX,IN.uv_HeightMap.y)).x; float3 norm = normal; float3 temp = norm; //a temporary vector that is not parallel to norm if(norm.x==1) temp.y+=0.5; else temp.x+=0.5; //form a basis with norm being one of the axes: float3 perp1 = normalize(cross(norm,temp)); float3 perp2 = normalize(cross(norm,perp1)); //use the basis to move the normal in its own space by the offset float3 normalOffset = -_HeightmapStrength * ( ( (n-me) - (s-me) ) * perp1 + ( ( e - me ) - ( w - me ) ) * perp2 ); norm += normalOffset; norm = normalize(norm); o.Normal = norm; o.Albedo = tex2D (_MainTex, IN.uv_MainTex + pannedUV).rgb * 1 - _CubeStrength; o.Albedo *= _Color.rgb; o.Emission = texCUBE (_Cube, WorldReflectionVector (IN, o.Normal)).rgb * _CubeStrength; o.Alpha = 0.8f; } inline fixed4 LightingNormalsHeight (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten) { viewDir = normalize(viewDir); lightDir = normalize(lightDir); s.Normal = normalize(s.Normal); float NdotL = dot(s.Normal, lightDir); _LightColor0.rgb = _LightColor0.rgb; fixed4 c; c.rgb = s.Albedo * saturate ( NdotL ) * _LightColor0.rgb * atten; c.a = 1.0; return c; } ENDCG } FallBack "VertexLit" }