Sign in to follow this  
jaafit

Using fog for water depth?

Recommended Posts

jaafit    116
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:
Quote:
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_FOGVERTEXMODE, D3DFOG_LINEAR);
	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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this