Water with distortion

00000000000000000000000000000000
0
Anonymous Oct 21, 2004 at 11:04

04-10-21.thm.jpg

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;
}

5 Replies

Please log in or register to post a reply.

7543b5c50738e23b200e69fe697ea85a
0
NomadRock 101 Oct 21, 2004 at 23:49

Looks good, but the water blends too well into the land, there are areas where I can’t tell where the land stops and the water starts.

22b3033832c5c699c856814b0cf80cb1
0
bladder 101 Oct 22, 2004 at 00:16

Yeah, it looks great except for where the land and water blend in. If you could make some (I forget the name of the white noise on top of water waves) surf (??) as the water hits the edges, it would look sweet!! But I suppose doing that you’ll need to calculate the intersection of the water with the land - and that will add quite a bit more complexity…

Fdbdc4176840d77fe6a8deca457595ab
0
dk 158 Oct 22, 2004 at 01:58

I like the fact that you have provided implementation details and some code. This is what developers benefit from the most besides seeing some eye candy.
Nice job!

6e0b32504d31ae07efc17f3322cdb147
0
SnprBoB86 101 Oct 22, 2004 at 22:38

Good work!

744d06ebf78d82e8667f1f7ad8392daf
0
SYS49152 101 Oct 28, 2004 at 10:11

the water looks great. cool that you share the shader-file. :)
you should add some detail texturing.

nice job !

  • Andy