Jump to content
  • Advertisement
Sign in to follow this  

Using fog for water depth?

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have implemented a basic water effect that supports reflection/refraction/and scrolling normal maps. Now I need to get depth effects working and get rid of the texture look-up glitch that occurs where the water meets the terrain. I've read elsewhere that you can use a rendering of the scene in white using black fog to get a depth map, from which you can calculate the depth of the water. From that thread:
render to a texture with all geometry as pure white, and render it with fog as black, starting from the camera and ending at your max view distance...By modulating the depth factor with the scene color and the water color, it is very easy to apply the desired effect.
I've attempted to do this but the results are somewhat poor. The main problem is banding. I'm using a D3DFMT_A8R8G8B8 render target when rendering the fog for the depth map, then dividing one of those channels (red) by FOGEND to get the distance from the camera to the terrain. This means that I'm using only 8 bits for a terrain that is anywhere between 1ft and 10,000ft away (I see now why depth buffers are 24bit)! So what do I do to get more precision in my depth map? I could use the actual depth map right but I hear this fog-based method is much faster? I'm also attempting to use D3DFMT_A2R10B10G10 but not having much success with that yet. Device states I'm using:
	gpDXDevice->LockRenderState( DXRS_AMBIENT, 0xffffffff );
	gpDXDevice->LockRenderState( DXRS_FOGENABLE, TRUE );
	gpDXDevice->LockRenderState( DXRS_FOGTABLEMODE, D3DFOG_NONE);
	gpDXDevice->LockRenderState( DXRS_RANGEFOGENABLE, TRUE);
	gpDXDevice->LockRenderState( DXRS_FOGCOLOR, DXFloatColor(0.f, 0.f, 0.f, 1.f) );
	gpDXDevice->LockRenderState( DXRS_FOGSTART, FtoDW(0.f) );
	gpDXDevice->LockRenderState( DXRS_FOGEND, FtoDW( 2000.f ) );	
	gpDXDevice->LockRenderState( DXRS_CULLMODE, D3DCULL_NONE );
You'll notice that my FOGEND value is 2000, which in my engine is feet. Typcial view distance however are up to 10 miles! So this FOGEND value is an attempt to get more resolution near the camera, sacrificing all depth information past 2000 ft. Here's the relevant code from my pixel shader:
	float fogEnd = 2000; // D3DRS_FOGEND
	float3 depthColor = tex2D(DepthSampler, refrUv); // reuse refraction coords
	float terrainDistance = (1 - depthColor.r) * fogEnd;
	float waterDepth = terrainDistance - viewDistance; // depth in feet
	float depthColorRatio = clamp(waterDepth / 150, 0, 1); 
	refractionColor.rgb = lerp(refractionColor.rgb, cgv_blue, depthColorRatio);
DepthSampler is the A8R8G8B8 render target, viewDistance is the distance from the camera to the pixel (I've confirmed this value is good) and cgv_blue is a blueish color. What can I do to get a more precise depth reading from this method? [Edited by - jaafit on March 20, 2007 7:05:13 PM]

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!