Uhh, yeah. I lack considerable skill in ShaderLab, but I seem to have proven myself an ample Dr. Frankenstein of shaders. I’ve been pulling bits and pieces out of various water shaders to try and make a nice indie water shader. Goals of my project are:
Make water transparent [Done]
Make surface ripple when it touches stuff [Started]
Make water light-affected [Attempted]
Shader "FX/Water (awesome)" {
Properties {
_horizonColor ("Horizon color", COLOR) = ( .172 , .463 , .435 , 0)
_WaveScale ("Wave scale", Range (0.02,0.15)) = .07
_ColorControl ("Reflective color (RGB) fresnel (A) ", 2D) = "" { }
_ColorControlCube ("Reflective color cube (RGB) fresnel (A) ", Cube) = "" { TexGen CubeReflect }
_BumpMap ("Waves Bumpmap (RGB) ", 2D) = "" { }
WaveSpeed ("Wave speed (map1 x,y; map2 x,y)", Vector) = (19,9,-16,-7)
_MainTex ("Fallback texture", 2D) = "" { }
_RippleMap ("RippleMap (RGB) ", 2D) = "ripple" {}
RipplePosition ("Ripple (x,y offset; x,y scale)", Vector) = (0.5, 0.5, 0.05, 0.05)
}
CGINCLUDE
// -----------------------------------------------------------
// This section is included in all program sections below
#include "UnityCG.cginc"
uniform float4 _horizonColor;
uniform float4 WaveSpeed;
uniform float4 RipplePosition;
uniform float _WaveScale;
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
V2F_POS_FOG;
float2 bumpuv[2] : TEXCOORD0;
float2 rippleuv[1];
float3 viewDir : TEXCOORD2;
};
v2f vert(appdata v)
{
v2f o;
float4 s;
PositionFog( v.vertex, o.pos, o.fog );
// scroll bump waves
float4 temp;
temp.xyzw = (v.vertex.xzxz + _Time.x * WaveSpeed.xyzw) * _WaveScale;
o.bumpuv[0] = temp.xy * float2(.4, .45);
o.bumpuv[1] = temp.wz;
o.rippleuv[0] = v.vertex.xz * float2(RipplePosition.w, RipplePosition.z) + float2(RipplePosition.x, RipplePosition.y);
// object space view direction
o.viewDir.xzy = normalize( ObjSpaceViewDir(v.vertex) );
return o;
}
ENDCG
// -----------------------------------------------------------
// Fragment program
Subshader {
Tags { "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Lighting On
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma fragmentoption ARB_fog_exp2
sampler2D _BumpMap;
sampler2D _RippleMap;
sampler2D _ColorControl;
half4 frag( v2f i ) : COLOR
{
half3 bump1 = tex2D( _BumpMap, i.bumpuv[0] ).rgb;
half3 bump2 = tex2D( _BumpMap, i.bumpuv[1] ).rgb;
half3 bump3 = tex2D( _RippleMap, i.rippleuv[0] ).rgb;
half3 bump = bump1 + bump2 + bump3 - 1.5;
half fresnel = dot( i.viewDir, bump );
half4 water = tex2D( _ColorControl, float2(fresnel,fresnel) );
half4 col;
col.rgb = lerp( water.rgb, _horizonColor.rgb, water.a );
col.a = _horizonColor.a;
col.a = water.a;
return col;
}
ENDCG
}
}
// -----------------------------------------------------------
// Radeon 9000
Subshader {
Tags { "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Pass {
CGPROGRAM
#pragma vertex vert
// just define 'vert' as a vertex shader, the code is included
// from the section on top
ENDCG
Program "" {
SubProgram {
Local 0, [_horizonColor]
"!!ATIfs1.0
StartConstants;
CONSTANT c0 = program.local[0];
EndConstants;
StartPrelimPass;
SampleMap r0, t0.str;
SampleMap r1, t1.str;
PassTexCoord r2, t2.str;
ADD r1, r0.bias, r1.bias; # bump = bump1 + bump2 - 1
DOT3 r2, r1, r2; # fresnel: dot (bump, viewer-pos)
EndPass;
StartOutputPass;
SampleMap r2, r2.str;
LERP r0.rgb, r2.a, c0, r2; # fade in reflection
col.a = water.a;
MOV r0.a, c0.a, r2.a;
EndPass;
"
}
}
SetTexture [_BumpMap] {}
SetTexture [_BumpMap] {}
SetTexture [_ColorControl] {}
}
}
// -----------------------------------------------------------
// Old cards
// three texture, cubemaps
Subshader {
Tags { "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Pass {
Color (0.5,0.5,0.5,0.5)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture * primary
}
SetTexture [_MainTex] {
Matrix [_WaveMatrix2]
combine texture * primary + previous
}
SetTexture [_ColorControlCube] {
combine texture +- previous, primary
Matrix [_Reflection]
}
}
}
// dual texture, cubemaps
Subshader {
Tags { "Queue" = "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Pass {
Color (0.5,0.5,0.5,0.5)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture
}
SetTexture [_ColorControlCube] {
combine texture +- previous, primary
Matrix [_Reflection]
}
}
}
// single texture
Subshader {
Tags { "RenderType"="Opaque" }
Pass {
Color (0.5,0.5,0.5,0)
SetTexture [_MainTex] {
Matrix [_WaveMatrix]
combine texture, primary
}
}
}
}
If you can help me further either of the two incomplete goals with your wonderful shadery knowledge, may God bless you.
Also, on the subject of the surface rippling, I’ve been siphoning code out of Proto’s Pro Water with 3 Bump Maps. Right now it pretty much just makes a single static ripple bump appear in the center of the water object.