Home » Community » Forums » DirectX and XNA » [MDX] Water Reflection Clipping Problem
Intel sponsors gamedev.net search:
Control Panel Register Bookmarks Who's Online Active Topics Stats FAQ Search

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 [MDX] Water Reflection Clipping Problem
Post New Topic  Post Reply 
I can't seem to get user clip planes working correctly to clip geometry below the water surface. Here is an extract of my code, I use HLSL for rendering:

device.ClipPlanes[0].Enabled = true;
Plane planeWater = new Plane(0f, 1f, 0f, 0f);
device.ClipPlanes[0].Plane = planeWater;
device.RenderState.Clipping = true;

terrain.Render(Matrix.Scaling(1.0f, -1.0f, 1.0f)) //render terrain upside-down




The clip plane seems dependent on the camera view matrix maybe, as the clip plane seems to move with the camera.

Thanks for any help,

James

 User Rating: 1060   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well, I'm not entirely sure what the problem might be exactly, as it's been a while since I worked on water reflection. But maybe the sample on this page can help you out. It does use the FFP to render the reflection, but the clipping code should be the same for any HLSL approach.

Hope this helps,


Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Clip planes are always in eye space, keep that in mind. If you're using a world space clip plane, you need to transform it accordingly.

 User Rating: 1898   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Are you sure that holds true for Managed DirectX, Promit? I've done some searching on MSDN, but I can't find anything useful on it.

My little sample project however suggests that user clipping planes in MDX can be defined in world-space and will get converted properly to eye space, using the View and Projection matrix set on the device. Here's my code to create the clipping plane, maybe the FromPointNormal method makes the difference?

[source=c#]
Plane clipPlane = Plane.FromPointNormal( Vector3.Empty, new Vector3(0, 1, 0));
device.ClipPlanes[0].Plane = clipPlane;
device.ClipPlanes[0].Enabled = true;
device.RenderState.Clipping = true;





Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I had a similar problem recently and I was able to fix it. See this thread
for details.

 User Rating: 1200   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Remigius - Your example is where I got my clip plane code from at first, but it seems clips planes are different in hlsl.

jamesw - thanks for the link..I have now added code to transform the plane by the camera view and projection matrices, but it sill doesn't work correctly.

Infact the blue band in the 2nd image never shows reflection, and sky is never reflected (unless I reverse the clip plane to point y=-1).

images showing problem

[source lang=c#]
rtsWater.BeginScene(rSurfaceWater);
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Transparent, 1.0f, 0);

device.RenderState.CullMode = Cull.Clockwise;
device.ClipPlanes[0].Enabled = true;
Plane planeWater = Plane.FromPointNormal(new Vector3(0,0,0), new Vector3(0, 1, 0));
device.ClipPlanes[0].Plane = planeWater;
device.RenderState.Clipping = true;

Vector3 pos = camera.GetPosition(); pos.Y = 0f;
skybox.Render(Matrix.Translation(pos) * Matrix.Scaling(1.0f, -1.0f, 1.0f)); //render skybox using FFP

planeWater.Transform(camera.GetViewingFrustum()); //transform plane for hlsl
device.ClipPlanes[0].Plane = planeWater;

terrain.Render(Matrix.Scaling(1.0f, -1.0f, 1.0f) * camera.GetViewingFrustum()); //render terrain using hlsl

device.RenderState.Clipping = false;
device.ClipPlanes[0].Enabled = false;
device.RenderState.CullMode = Cull.CounterClockwise;

rtsWater.EndScene(Filter.None);




 User Rating: 1060   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hmmm... To test this, I've converted my sample project to use a simple shader and spent the last 2 hours trying to get it to work, but the transform on the plane just doesn't seem to work out...

Download the sample project, with this rendering code:

[source lang=c#]
device.RenderState.CullMode = Cull.None;
effect.SetValue("ViewProjection", camera.ViewMatrix * camera.ProjectionMatrix );

Plane clipPlane = Plane.FromPointNormal( Vector3.Empty, new Vector3(0, 1, 0));
clipPlane.Transform( camera.ViewMatrix * camera.ProjectionMatrix );

device.ClipPlanes[0].Plane = clipPlane;
device.ClipPlanes[0].Enabled = true;				
device.RenderState.Clipping = true;

int numPasses = effect.Begin( FX.None );

for (int i = 0; i < numPasses; i++)
{
	effect.BeginPass(i);					
	mesh.DrawSubset(0);
	effect.EndPass();
}

effect.End();






This code does seem to transform the clipping plane, but it doesn't move along with the camera... In fact it seems to be moving (or rather rotating) to the exact opposite direction of the camera. Messing around with the view matrix (inverting, remapping) doesn't work and should be redundant anyway, right?

Can anyone tell me what I'm doing wrong?


Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

When transforming the clip planes, are you using the normal world matrix or the reflected matrix (I hope I'm not completely off here :))?

 User Rating: 1716   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

If you're referring to my project, you're a bit off I made this project to test the clip plane transform with a simple teapot, so I'm not doing any reflection rendering. From what I can tell, my code is doing the same as the OP's and I'm not getting the right result at all... So I guess if you can fix my code, that should solve the OP's problem too.

Thanks in advance :)


Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Here is the code that I am using which is working, maybe it will help.
//normalize the plane which is required for the transforms
D3DXPLANE tempPlane = worldSpacePlane;
	D3DXPLANE viewSpacePlane;
	D3DXPlaneNormalize(&tempPlane, &tempPlane);

	//transform the plane into view space
	D3DXMATRIX  tempMatrix = dxAppSettings.matView;
	D3DXMatrixInverse(&tempMatrix, NULL, &tempMatrix);
	D3DXMatrixTranspose(&tempMatrix, &tempMatrix);
	D3DXPlaneTransform(&viewSpacePlane, &tempPlane, &tempMatrix);

	//transform the plane into clip space, or projection space
	tempMatrix = dxAppSettings.matProj;
	D3DXMatrixInverse(&tempMatrix, NULL, &tempMatrix);
	D3DXMatrixTranspose(&tempMatrix, &tempMatrix);
	D3DXPlaneTransform(&clipSpacePlane, &viewSpacePlane, &tempMatrix);


Before I got this working i set up a slider that controlled the d value of the clip plane. Adjusting the slider helped me to figure out exactly what was going on in realtime.

 User Rating: 1200   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Right, so following jamesw's latest post, this line works in remigius's code:

clipPlane.Transform(Matrix.TransposeMatrix(Matrix.Invert(camera.ViewMatrix)) * 
    Matrix.TransposeMatrix(Matrix.Invert(camera.ProjectionMatrix)));
I'm not too sure what the logic behind it is :).

 User Rating: 1716   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hehe, I don't get it one bit at all, but it works like a charm

[source lang=c#]
Plane clipPlane = Plane.FromPointNormal( Vector3.Empty, new Vector3(0, 1, 0));
clipPlane.Normalize();

Matrix tempMatrix = camera.ViewMatrix;
tempMatrix.Invert();
tempMatrix.Transpose( tempMatrix );
clipPlane.Transform( tempMatrix );

tempMatrix = camera.ProjectionMatrix;
tempMatrix.Invert();
tempMatrix.Transpose( tempMatrix );
clipPlane.Transform( tempMatrix );

device.ClipPlanes[0].Plane = clipPlane;
device.ClipPlanes[0].Enabled = true;				
device.RenderState.Clipping = true;



Thanks for helping both of us out!


Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ Blogthing ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

 User Rating: 1683   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by sirob
Right, so following jamesw's latest post, this line works in remigius's code:

clipPlane.Transform(Matrix.TransposeMatrix(Matrix.Invert(camera.ViewMatrix)) * 
    Matrix.TransposeMatrix(Matrix.Invert(camera.ProjectionMatrix)));
I'm not too sure what the logic behind it is :).


Sure thing! In the C++ docs for D3DXPlaneTransform() it says the plane has to be normalized and the matrices have to be inverted and transposed before sending them to the function. Gotta go to class.

 User Rating: 1200   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Thanks for your help guys, I managed to sort it too.

Unfortunately a new problem seems apparent with the displacement of texture coords. I decided to start a new thread though:
link to thread


 User Rating: 1060   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: