Sgt. Conker We are "absolutely fine"

3Nov/097

Article : Realistic Soft Edged Water In XNA

Smoothing the Shoreline

Our next step is to add the logic to the pixel shader in order to get a fade factor from zero water to fully opaque water. Replace your pixel shader with this one.

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float2 screenTexCoords = 0.5 * (float2(input.ClipPos.x, input.ClipPos.y) / input.ClipPos.w) + 0.5;
    screenTexCoords.y = 1 - screenTexCoords.y;

    // Get the terrain depth
    float sceneViewZ = tex2D(DepthSampler, screenTexCoords).r;

    // Get the water plane depth
    float waterViewZ = length(input.ViewPos) / FarPlane;

    // Get the range of depth from waterplane to terrain
    float depthRange = (sceneViewZ - waterViewZ);

    const float shoreFalloff = 2.0f;
    const float shoreScale = 5.0f;

    // calculate a transparency value using a power function
    float alpha = max(pow(depthRange , shoreFalloff) * FarPlane * shoreScale, 0);

    return float4(0, 0, 1, saturate(alpha));
}

The shoreFalloff and shoreScale constants here can be made global to the shader, and set from C#. A value of 1.0f would mean no falloff, and higher values mean a longer a falloff. When using a higher falloff you probably want a higher scale, otherwise the falloff wont fade quick enough.

Also, since we are now alpha blending for the moment, we need to set the blend source and destination states. In the Planar Water draw method, set AlphaBendEnable and AlphaTestEnable to true, and the source and destination blend states to SourceAlpha and InverseSourceAlpha, as follows:

renderState.AlphaTestEnable = true;
renderState.AlphaBlendEnable = true;
renderState.SourceBlend = Blend.SourceAlpha;
renderState.DestinationBlend = Blend.InverseSourceAlpha;

About CorporalX

Professional XNA/.NET developer.
Comments (7) Trackbacks (0)
  1. Finally, a subject on just water and not necessarily ‘adding’ water for Xna.
    I am going to try this out as my goal is to just do water itself in Xna, for now.

  2. This is very similar to the technique I use to render water as a post processing pass. In my implementation I render geometry into the stencil buffer and output linear view space depth. Then run a full screen quad over the results of that to produce the water in the back-buffer with stencil rejection enabled.

  3. Hey,

    is there a way you could re-upload the sample and images for this tutorial? Would be really nice.
    BTW this is just the tutorial i’ve been looking for for months … thank you soooo much :D

  4. Existence – Fixed the images and sample download.

  5. Hey Sarge,

    The pixel shader broke when I ran this under Xna 3.0. Band-aid solution: saved the pixel shader to a static variable before executing begin command with the Effect, then set it back once it went to null. Is there a quick fix to get around the ravages of Microsoft progress?

    Best,
    Dave

  6. Nota bene: my previous fix didn’t really work. If you receive the debugging message about not having a valid vertex or pixel shader, then you will probably have to set the pixel shader device version to 2 in the .fx file, instead of 3.

  7. This sample doesnt seem to work for me it causes problems with the for loops:

    for (int x = 0; x < Tesselation-1; x++)

    it underlines the ‘;’ after -1 and the ‘)’


Leave a comment


*

No trackbacks yet.