# Water / Terrain - Use the stencil buffer?

This topic is 4280 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey everyone :) I just turned my water in something nicer, allowing me to go beyond a single water plane. I use a pixel shader to get the nice water blending at the sides. For this to work, I turn the z-buffer checks off, but the z-write is still enabled. If I turn the Z-buffer checks on, I get very straight corners because of the low-res terrain polygons (the terrain is a few thousand poly's) Now, the problem is that, when the player is at one side of a hill/mountain, and there is water on the other side, the water will shine right through the terrain. I was wondering if it would be possible to use the stencil buffer to solve this, somehow. I haven't had real use for stencil buffers yet in my game developing time. Or maybe a fancy Z comparison check? The Idea is that: The water poly's are not "cut off" by the terrain poly's. But the water should not shine through the terrain hills, when looking from the other side. If this is not clear, I can provide a screenshot :) Many thanks for any suggestions :)

##### Share on other sites
Quote:
 Or maybe a fancy Z comparison check?

You could try to play with the depth bias.

##### Share on other sites
Hm, I guess I could give that a try. But I thought depthbias was quite driver dependent on it's use/function.

##### Share on other sites
I really don't think the bias will do anything in this case, but if you somehow find a way please do let us know.

I am pretty certain you can use the stencil for this, but performance might be questionable. I think you'd have to render all the terrain which is above sea level to the stencil, then again for display, so it's a little expensive. Then use the stencil to filter out where not to render the water. I haven't done it, but its what the Stencil is used for.

You could also use this technique to cut a cave into the side of the terrain for example.

##### Share on other sites
I'm not sure if this would work for a 3d water surface, but for a water plane you can blend the reflection out near the edges.

Before:

After:

This is done using the heightmap as input to the water pixel shader, and then scaling and clamping it into the range you want, to eventually look like this:

I'm still working on getting higher precision, because with a 16 bit heightmap I get a lot of banding. The edge factor is useful for scaling down the reflection and refraction distortion too.

##### Share on other sites
Quote:
 Original post by ajolingHm, I guess I could give that a try. But I thought depthbias was quite driver dependent on it's use/function.

No, that was Z bias, and older version of this functionality. Depth bias is well defined.

Not saying it's the perfect answer, but if you want to say that something close to the real Z shouldn't be culled but something far should, it seems like a good candidate.

##### Share on other sites
Quote:
 Original post by jameswI'm not sure if this would work for a 3d water surface, but for a water plane you can blend the reflection out near the edges.Before: After: This is done using the heightmap as input to the water pixel shader, and then scaling and clamping it into the range you want, to eventually look like this: I'm still working on getting higher precision, because with a 16 bit heightmap I get a lot of banding. The edge factor is useful for scaling down the reflection and refraction distortion too.

Hi James,

That's exactly what I am doing too. It creates a very nice effect, but , because I turn off Z bufering, the water shines through. I could ofcourse make the water less "wide" than the terrain/river "gap". but I prefer a different approach.

ET3D: Going to try the depth bias. :)

##### Share on other sites
Okay, the depthbias function is weird :) I was using 'big' values like 1-3.0f and it looked really odd. Some obejcts would suddenly be "behind" the water for example.

but. I tweaked it down to 0.0005, and the water is rendered okay. Z-buffer is enabled (no more shine through), and my objects are still fine.

Conclusion: I'm happy :)

##### Share on other sites
ajoling, could you post some screens of your 3d water? I'd like to see what you're working on, especially the shorelines.

##### Share on other sites
Wow, jamesw, would you be willing to point me in the right direction on how to make an effect like that? I'm pretty clueless on pixel shaders, I'd love to know how that's actually done.

##### Share on other sites
Sure jamesw!

Here are two screenshots for you. The terrain might look 'small' but it's an RTS game and will be quite zoomed in. :) I'd like to have the specular highlight which you have as well and some more wavey effect.

I think I have reflections currently disabled, trying to find out how to squeeze more FPs juice out of everything. My card ain't the best videocard, but I still think it should do better. Rendering water really kills the fps.

Distant view:

Closer (excuse the texture choice):

Geometry (simple return float4(0.0f,1.0f,0.0f,1.0f) in shader)

Hope this is useful to you :)

##### Share on other sites
Hm, I spent a while on the shader. It's nearly similar now, and because of a few specifics, does not fit into PS1.4 :(, but still it's 20-30fps faster for me:

Although maybe I will use one pow() (or something) to make the water blend faster on the sides. Now one side is less shorelined than the other.

Original:
approximately 26 instruction slots used (3 texture, 23 arithmetic)

New:
approximately 10 instruction slots used (3 texture, 7 arithmetic)

##### Share on other sites
Quote:
 Original post by ajoling

I'd say your problem is that you're using a heightmap of quads instead of a heightmap of triangles. Try instead making the heightmap with patches like this:

H***********H*---------*-**-------*---**-----*-----**---*-------**-*---------*H***********H

**************-----------**-----------**-----H-----**-----------**-----------**************(H means a height sample in your heightmap image or 2d array)

Then your edges will be smooth without any need to turn off z-buffering. That would solve a lot of your problems I think...

Btw nice with a western game, way too few are made. I wish you good luck and hope it'll be available to buy or as freeware soon :)

##### Share on other sites
Thanks :). I will have a look at it. I'm probably going to alter my terrain generator a bit anyway, I have way too much quadtree nodes in my terrain. Rendering those seperately takes more time than rendering a bigger chunk.

About the western games: Yeah, my favorite 'game' is a mod called "Badlands" for Unreal tournament 1. Nothing beats walking around with a Sharps plains rifle. Truly one of the best mods made for the game.

And because of the time I spent in this game, I'm afraid it won't be freeware :). But, it won't be expensive either.. :). If I finish it ofcourse.

##### Share on other sites
Quote:
 Wow, jamesw, would you be willing to point me in the right direction on how to make an effect like that? I'm pretty clueless on pixel shaders, I'd love to know how that's actually done.

The best place to start is right here on gamedev, Yann's water article. And once you have that stuff down take a look at the 'Generic refraction simulation' article in GPU Gems 2 as well as the one about animation water in ShaderX3. Both of these articles have a wealth of knowledge on water effects and the GPU Gems 2 one has a full working sample. Just don't copy it like so many do, figure out how it works and make your own.

Quote:
 Here are two screenshots for you.

Thanks! You really have the edge fadeout down, I can't see any sharp edges at all. How come you don't have any banding? Or is it just too far away for that. When I scale the depth values into a good range to be a blend factor they band like crazy.

Quote:
 approximately 10 instruction slots used (3 texture, 7 arithmetic)

I'm using 67 arithmetic =( It currently rapes cards with low pixel power. I have to find a way to fit it in ps2.0.

##### Share on other sites
Quote:
Original post by jamesw
Quote:
 Wow, jamesw, would you be willing to point me in the right direction on how to make an effect like that? I'm pretty clueless on pixel shaders, I'd love to know how that's actually done.

The best place to start is right here on gamedev, Yann's water article. And once you have that stuff down take a look at the 'Generic refraction simulation' article in GPU Gems 2 as well as the one about animation water in ShaderX3. Both of these articles have a wealth of knowledge on water effects and the GPU Gems 2 one has a full working sample. Just don't copy it like so many do, figure out how it works and make your own.

Quote:
 Here are two screenshots for you.

Thanks! You really have the edge fadeout down, I can't see any sharp edges at all. How come you don't have any banding? Or is it just too far away for that. When I scale the depth values into a good range to be a blend factor they band like crazy.

Quote:
 approximately 10 instruction slots used (3 texture, 7 arithmetic)

I'm using 67 arithmetic =( It currently rapes cards with low pixel power. I have to find a way to fit it in ps2.0.

Yeah, my reflection is based on Yann's water article. I guess I should look for some refraction articles myself. Most of them are plain ASM though, which I have started to dislike ever since I started on DX9. :).

I've used two techniques for my water james.

Method 1 (old):

The heightmap is sampled on the appropriate coordinate. Since I know what my min/max terrain values are, I can multiply the .r * maxterreinheight. This gives me the (near) perfect height. I also knew the water level (I first had a fixed water height).

So, I did something like:

float fTerrainHeight = tex2D(HeightMap, vPos).r * fTerrainMaxHeight;
float fWaterCalc = fWaterLevel-(fTerrainHeight);
float fAlpha = ((fWaterCalc+0.25f) / fWaterLevel);

This is old HLSL code, I might have modified it in a version so that it doesn't work.

It produces a similar effect as my new version.

Method 2:

Now I have multi level water (just not for reflections, a whole different challenge with clipping planes..). And I cheated on the water height.

I removed the "river" in my original heightmap, and created a watermap. This watermap is like a heightmap, but it tells me where to "dig" rivers/lakes. I have limited the range of depth: 0 = 0, 255 = 4. This depends on your unit system.

When generting the terrain, the watermap and heightmap will be 'merged'. so rivers/lakes will automatically be shown in the vertexdata. And, as bonus, I still have this "water map". Submitting this to the pixelshader gives me exact knowledge where to start blending. I can actually immediatly cull any pixels which are black too!

Ofcourse, you can generate this map from a fixed (known) waterlevel - height. And submit this texture to the shader.

Hope this works out for you. I thought my idea was pretty cool, and the water looks almost commercial quality :-).