
Description
The screenshot shows water with distortion effects.
Implementation details:
1. Render water using 2 passes;
2. In first pass, I render the scene into reflective-texture with mirror transform matrix;
3. In second pass, I render the water with reflective-texture;
4. In order to add distortion to water, I grab the normal from the normal-map in Water-Pixel Shader code (provided below) and add this normal to the texture coordinates for grabing the reflective-texture.
Advantages of this method:
1. Rendering water whose area is large just needs two triangle;
2. Normal-map is repeated, which means the normal-map can be low-resolution;
I think this method is suitable for rendering huge water with low triagles and low memory foot-print;
Here's the pixel shader program:
struct VS_OUTPUT
{
float4 Pos : POSITION;
float4 Tex0 : TEXCOORD0;
float2 Tex1 : TEXCOORD1;
};
VS_OUTPUT VS(float4 Pos : POSITION,
float2 Tex : TEXCOORD0)
{
VS_OUTPUT Out;
Out.Pos = mul(Pos, modelViewProj);
Out.Tex0 = mul(Pos, texTransform);
Out.Tex1 = Tex;
return Out;
}
sampler sReflect = sampler_state
{
Texture = (tReflect);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
};
sampler sAlpha = sampler_state
{
Texture = (tDepth);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
ADDRESSU = CLAMP;
ADDRESSV = CLAMP;
};
sampler sNormal = sampler_state
{
Texture = (tNormal);
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
ADDRESSU = WRAP;
ADDRESSV = WRAP;
};
float4 PS(VS_OUTPUT In) : COLOR
{
float4 Out;
// grab value from depth map as alpha
Out.w = tex2D(sAlpha, In.Tex1).w;
// scale tex coordinate for repeat normal map
float2 rUv;
rUv.x = In.Tex1.x*uNormalRep;
rUv.y = In.Tex1.y*vNormalRep;
// grab value from normal map
float3 nor = tex2D(sNormal, rUv).xyz;
// scale and offset from [0,1] into [-1,1]
nor.x = nor.x * 2.0f - 1.0f;
nor.y = nor.y * 2.0f - 1.0f;
nor.z = nor.z * 2.0f - 1.0f;
// normal scale
float eff = fNormalScale*In.Tex0.w;
// offset tex coordinate for reflective texture with normal
float4 Uv = In.Tex0;
Uv.x += nor.x*eff;
Uv.y += nor.y*eff;
Uv.z += nor.z*eff;
// grab value from reflective map
Out.xyz = tex2Dproj(sReflect, Uv).xyz;
// lerp value between water constant value and reflective value
// Out = lerp(crlWater, Out, Out.w);
return Out;
}












