Sign in to follow this  

[XNA] Water reflection problems

This topic is 3569 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 am quite new to XNA, and I have been following Riemers tutorials. Once I completed those, I started on my own project. All has been going well so far, except I can't get the reflection on the water to work. Then I realized that I was missing some code to create the matrix for the reflection method. So it works. Sort of. The reflection does not reflect properly. This image is the reflection texture that XNA generated: http://i209.photobucket.com/albums/bb101/Mavix_2007/reflection.jpg This already explains my problem, because there is no grass above the water, or next to it if I'm in the middly of the lake. Using this reflection texture, I will try to explain what happens on the water. First, three screenshots with me panning the camera down: http://i209.photobucket.com/albums/bb101/Mavix_2007/01.jpg http://i209.photobucket.com/albums/bb101/Mavix_2007/02.jpg http://i209.photobucket.com/albums/bb101/Mavix_2007/03.jpg If I keep the camera at the same rotation as in picture two, and I move forward quickly, then it looks as if the terrain underneath has been inverted and is moving on the water. Its almost as if its reflecting whats underneath the water, which is obvious looking at the reflection texture. I have used exactly the code that Reimers uses. Does anyone know whats going on?

Share this post


Link to post
Share on other sites
I agree with FoxHunter2, a lot of people are having trouble with the Up vector being Z.

Is your shader the exact same as Riemer's?

Can you post the water drawing function and the code segment where you get your Reflection Texture?

Share this post


Link to post
Share on other sites
I use Z as the up vector. The water code is the same as Riemers, and his series four code works perfectly. I've taken some new screenshots to give you a better idea of whats going on(Once again panning down the camera):

Photobucket

Photobucket

Photobucket

My shader code is exactly the same as Riemers.

Here's the water code:

//From Game1.cs
protected override void Draw(GameTime gameTime)
{
map.DrawReflectionMap(camera, device, this);
map.DrawRefractionMap(camera, device, this);

graphics.GraphicsDevice.Clear(Color.SkyBlue);

map.DrawMap(camera, device);
map.DrawWater(camera, device, this);

objectNodes.drawObjects(camera);

base.Draw(gameTime);
}

public void DrawEverythingExceptWater()
{
map.DrawMap(camera, device);
objectNodes.drawObjects(camera);
}

//From mapHandler.cs
public void DrawWater(CameraHandler camera, GraphicsDevice device, Game1 game)
{
waterEffect.CurrentTechnique = waterEffect.Techniques["Water"];

Matrix worldMatrix = Matrix.Identity;
waterEffect.Parameters["xWorld"].SetValue(worldMatrix);
waterEffect.Parameters["xView"].SetValue(camera.viewMatrix);
waterEffect.Parameters["xReflectionView"].SetValue(reflectionViewMatrix);
waterEffect.Parameters["xProjection"].SetValue(camera.projectionMatrix);
waterEffect.Parameters["xReflectionMap"].SetValue(reflectionMap);
waterEffect.Parameters["xRefractionMap"].SetValue(refractionMap);
waterEffect.Parameters["xWaterBumpMap"].SetValue(waterBumpMap);
waterEffect.Parameters["xWaveLength"].SetValue(0.1f);
waterEffect.Parameters["xWaveHeight"].SetValue(0.3f);
waterEffect.Parameters["xCamPos"].SetValue(camera.cameraPosition);
waterEffect.Parameters["xTime"].SetValue(game.elapsedTime);
waterEffect.Parameters["xWindForce"].SetValue(20.0f);

Matrix windDirection = Matrix.CreateRotationZ(MathHelper.PiOver2);
waterEffect.Parameters["xWindDirection"].SetValue(windDirection);

waterEffect.Begin();
foreach (EffectPass pass in waterEffect.CurrentTechnique.Passes)
{
pass.Begin();
device.VertexDeclaration = new VertexDeclaration(device, VertexPositionTexture.VertexElements);
device.DrawUserPrimitives(PrimitiveType.TriangleList, waterVertices, 0, 2);
pass.End();
}
waterEffect.End();
}

public void DrawReflectionMap(CameraHandler camera, GraphicsDevice device, Game1 game)
{
Vector3 planeNormalDirection = new Vector3(0, 0, 1);
planeNormalDirection.Normalize();
Vector4 planeCoefficients = new Vector4(planeNormalDirection, -waterHeight);

Matrix camMatrix = reflectionViewMatrix * camera.projectionMatrix;
Matrix invCamMatrix = Matrix.Invert(camMatrix);
invCamMatrix = Matrix.Transpose(invCamMatrix);

planeCoefficients = Vector4.Transform(planeCoefficients, invCamMatrix);
Plane reflectionClipPlane = new Plane(planeCoefficients);

device.ClipPlanes[0].Plane = reflectionClipPlane;
device.ClipPlanes[0].IsEnabled = true;

device.SetRenderTarget(0, reflectionRenderTarget);
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.SkyBlue, 1.0f, 0);
game.DrawEverythingExceptWater();
device.ResolveRenderTarget(0);
reflectionMap = reflectionRenderTarget.GetTexture();
device.SetRenderTarget(0, null);

device.ClipPlanes[0].IsEnabled = false;
}

public void UpdateReflectionCamera(CameraHandler camera, Game1 game)
{
float reflectionCamZCoord = -camera.cameraPosition.Z + 2 * waterHeight;
Vector3 reflectionCamPosition = new Vector3(camera.cameraPosition.X, camera.cameraPosition.Y, reflectionCamZCoord);

float reflectionTargetZCoord = -camera.targetPos.Z + 2 * waterHeight;

Vector3 reflectionCamTarget = new Vector3(camera.targetPos.X, camera.targetPos.Y, reflectionTargetZCoord);

Vector3 forwardVector = reflectionCamTarget - reflectionCamPosition;
Vector3 sideVector = Vector3.Transform(new Vector3(1, 0, 0), camera.cameraRotation);
Vector3 reflectionCamUp = Vector3.Cross(sideVector, forwardVector);

reflectionViewMatrix = Matrix.CreateLookAt(reflectionCamPosition, reflectionCamTarget, reflectionCamUp);
}

Share this post


Link to post
Share on other sites
I notice you're not passing the 'reflectionViewMatrix' Matrix into the Map.DrawMap function. I believe Reimer passes the 'reflectionViewMatrix' in when drawing the terrain and sky onto the reflection texture for use as the View Matrix.


private void DrawTerrain(Matrix currentViewMatrix)
{
.
.
.
Matrix worldMatrix = Matrix.Identity;
effect.Parameters["xWorld"].SetValue(worldMatrix);
effect.Parameters["xView"].SetValue(currentViewMatrix);

private void DrawReflectionMap()
{
.
.
.
DrawTerrain(reflectionViewMatrix);
DrawSkyDome(reflectionViewMatrix);


[Edited by - Mr Explody on March 6, 2008 11:59:25 PM]

Share this post


Link to post
Share on other sites

This topic is 3569 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.

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