Jump to content
  • Advertisement
Sign in to follow this  
iassc222

Depth problem when facing backwards? C#XNA

This topic is 2538 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

So i've been following a number of XNA 3d tutorials and I have gotten a basic terrein goin on with highmap loaded from a bmp file, and mouse look with basic collision/gravity

Problem is with depth, like if Im looking at a mountain the stuff behind it will be drawn on top of it.
But it is only when the camera is faced to look somewhere that has lower Z than camera position.

So if this is Z axis:
---->
and dir of arrow is Z going positive up, and the camera is facing this way: (< is facing right > is facing left)
---->
<
Then there is no depth problems, but if camera is facing this way:
---->
>
Then depth is bad.
I hope you understand what I mean :S

I have no clue what is wrong!

This is my draw function for drawing the terrein:

protected override void Draw(GameTime gameTime)
{
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

RasterizerState rs = new RasterizerState();
rs.CullMode = CullMode.CullCounterClockwiseFace;


device.RasterizerState = rs;
Matrix worldMatrix = Matrix.CreateTranslation(-terrainWidth / 2.0f, 0, terrainHeight / 2.0f) * Matrix.CreateRotationY(angle);
effect.CurrentTechnique = effect.Techniques["Colored"];
effect.Parameters["xView"].SetValue(viewMatrix);
effect.Parameters["xProjection"].SetValue(projectionMatrix);
effect.Parameters["xWorld"].SetValue(worldMatrix);
Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f);
lightDirection.Normalize();
effect.Parameters["xLightDirection"].SetValue(lightDirection);
effect.Parameters["xAmbient"].SetValue(0.1f);
effect.Parameters["xEnableLighting"].SetValue(true);
device.Indices = myIndexBuffer;
device.SetVertexBuffer(myVertexBuffer);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
spriteBatch.Begin();
spriteBatch.DrawString(DebugFont, "Position: " + Cam.X.ToString() + "," + Cam.Y.ToString() + "," + Cam.Z.ToString(), new Vector2(5, 5), Color.White);
spriteBatch.End();

base.Draw(gameTime);
}


Also, this is my function to initially setup the view/projection matrix:

private void SetUpCamera()
{
Vector3 UP = new Vector3();
UP.Y = (float)Math.Sin(CamAngleY) * 2.5f;
viewMatrix = Matrix.CreateLookAt(Cam, new Vector3(Cam.X, Cam.Y - 2f, Cam.Z + 9f), UP);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 0.5f, 5000.0f);
}


Also, after I have done in update and checked mouselook and moving, I call this to update camera:

private void UpdateCamera()
{
Vector3 UP = new Vector3();
UP.Y = (float)Math.Sin(CamAngleY - ((180/Math.PI)*90)) * 2.5f;
Window.Title = "X:" + Cam.X.ToString() + "|Y:" + Cam.Y.ToString() + "|Z:" + Cam.Z.ToString() + "|YA:"+CamAngleY.ToString() +
"::" + CamAngleX.ToString();
Vector3 V = new Vector3((float)Math.Cos(CamAngleX) * 20, (float)Math.Sin(CamAngleY) * 64, (float)Math.Sin(CamAngleX) * 20);

viewMatrix = Matrix.CreateLookAt(Cam, new Vector3(Cam.X + V.X, Cam.Y+V.Y, Cam.Z+V.Z), UP);
}



I have tried it feels like a million things but I cannot figure out what is wrong :(

If anybody has any ideas, that would be helpful :) :(

Here is my whole code for reference if that would be helpful:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame1
{
public class Game1 : Microsoft.Xna.Framework.Game
{
public struct VertexPositionColorNormal
{
public Vector3 Position;
public Color Color;
public Vector3 Normal;
public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
(
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(sizeof(float) * 3, VertexElementFormat.Color, VertexElementUsage.Color, 0),
new VertexElement(sizeof(float) * 3 + 4, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0)
);
}
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
GraphicsDevice device;
VertexBuffer myVertexBuffer;
IndexBuffer myIndexBuffer;
Effect effect;
VertexPositionColorNormal[] vertices;
Matrix viewMatrix;
Matrix projectionMatrix;
int[] indices;
private float angle = 0f;
private int terrainWidth = 4;
private int terrainHeight = 3;
private float[,] heightData;
bool CaptureMouse = true;
Vector3 Cam = new Vector3(0f, 60f, -80f);
float CamAngleX = 0f;
float CamAngleY = 0f;
float CamHeight = 20f;
float CamYSpd = 0.0f;
SpriteFont DebugFont;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.IsMouseVisible = true;
}
protected override void Initialize()
{
graphics.PreferredBackBufferWidth = 500;
graphics.PreferredBackBufferHeight = 500;
graphics.IsFullScreen = false;
graphics.ApplyChanges();
Window.Title = "GAH";

base.Initialize();
}
private void CopyToBuffers()
{
myVertexBuffer = new VertexBuffer(device, VertexPositionColorNormal.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
myVertexBuffer.SetData(vertices);
myIndexBuffer = new IndexBuffer(device, typeof(int), indices.Length, BufferUsage.WriteOnly);
myIndexBuffer.SetData(indices);
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
graphics.PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8;

device = graphics.GraphicsDevice;
effect = Content.Load<Effect>("effects"); SetUpCamera();
DebugFont = Content.Load<SpriteFont>("f_debug");
Texture2D heightMap = Content.Load<Texture2D>("hightmap1"); LoadHeightData(heightMap);
SetUpVertices();
SetUpIndices();
CalculateNormals();
CopyToBuffers();
}
protected override void UnloadContent()
{
}
private void SetUpVertices()
{
float minHeight = float.MaxValue;
float maxHeight = float.MinValue;
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainHeight; y++)
{
if (heightData[x, y] < minHeight)
minHeight = heightData[x, y];
if (heightData[x, y] > maxHeight)
maxHeight = heightData[x, y];
}
}
vertices = new VertexPositionColorNormal[terrainWidth * terrainHeight];
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainHeight; y++)
{
vertices[x + y * terrainWidth].Position = new Vector3(x, heightData[x, y], -y);
if (heightData[x, y] < minHeight + (maxHeight - minHeight) / 4)
vertices[x + y * terrainWidth].Color = Color.Blue;
else if (heightData[x, y] < minHeight + (maxHeight - minHeight) * 2 / 4)
vertices[x + y * terrainWidth].Color = Color.Green;
else if (heightData[x, y] < minHeight + (maxHeight - minHeight) * 3 / 4)
vertices[x + y * terrainWidth].Color = Color.Brown;
else
vertices[x + y * terrainWidth].Color = Color.White;
}
}
}
private void SetUpIndices()
{
indices = new int[(terrainWidth - 1) * (terrainHeight - 1) * 6];
int counter = 0;
for (int y = 0; y < terrainHeight - 1; y++)
{
for (int x = 0; x < terrainWidth - 1; x++)
{
int lowerLeft = x + y * terrainWidth;
int lowerRight = (x + 1) + y * terrainWidth;
int topLeft = x + (y + 1) * terrainWidth;
int topRight = (x + 1) + (y + 1) * terrainWidth;
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
}
private void CalculateNormals()
{
for (int i = 0; i < vertices.Length; i++)
vertices.Normal = new Vector3(0, 0, 0);
for (int i = 0; i < indices.Length / 3; i++)
{
int index1 = indices[i * 3];
int index2 = indices[i * 3 + 1];
int index3 = indices[i * 3 + 2];
Vector3 side1 = vertices[index1].Position - vertices[index3].Position;
Vector3 side2 = vertices[index1].Position - vertices[index2].Position;
Vector3 normal = Vector3.Cross(side1, side2);
vertices[index1].Normal += normal;
vertices[index2].Normal += normal;
vertices[index3].Normal += normal;
}
for (int i = 0; i < vertices.Length; i++)
vertices.Normal.Normalize();
}
private void LoadHeightData(Texture2D heightMap)
{
terrainWidth = heightMap.Width;
terrainHeight = heightMap.Height;
Color[] heightMapColors = new Color[terrainWidth * terrainHeight];
heightMap.GetData(heightMapColors);
heightData = new float[terrainWidth, terrainHeight];
for (int x = 0; x < terrainWidth; x++)
for (int y = 0; y < terrainHeight; y++)
heightData[x, y] = heightMapColors[x + y * terrainWidth].R / 5.0f;
}
private void SetUpCamera()
{
Vector3 UP = new Vector3();
UP.Y = (float)Math.Sin(CamAngleY) * 2.5f;
viewMatrix = Matrix.CreateLookAt(Cam, new Vector3(Cam.X, Cam.Y - 2f, Cam.Z + 9f), UP);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 0.5f, 5000.0f);
}
private void UpdateCamera()
{
Vector3 UP = new Vector3();
UP.Y = (float)Math.Sin(CamAngleY - ((180/Math.PI)*90)) * 2.5f;
Window.Title = "X:" + Cam.X.ToString() + "|Y:" + Cam.Y.ToString() + "|Z:" + Cam.Z.ToString() + "|YA:"+CamAngleY.ToString() +
"::" + CamAngleX.ToString();
Vector3 V = new Vector3((float)Math.Cos(CamAngleX) * 20, (float)Math.Sin(CamAngleY) * 64, (float)Math.Sin(CamAngleX) * 20);

viewMatrix = Matrix.CreateLookAt(Cam, new Vector3(Cam.X + V.X, Cam.Y+V.Y, Cam.Z+V.Z), UP);
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
float mx = Mouse.GetState().X - (graphics.PreferredBackBufferWidth / 2);
float my = Mouse.GetState().Y - (graphics.PreferredBackBufferHeight / 2);
mx /= 10;
my /= 10;
KeyboardState keyState = Keyboard.GetState();
MouseState ms = Mouse.GetState();
float w = terrainWidth / 2;
float h = terrainHeight / 2;
if (Cam.X < -w+5)
Cam.X = -w+5;
if (Cam.X > w-5)
Cam.X = w-5;
if (Cam.Z < -h+5)
Cam.Z = -h+5;
if (Cam.Z > h-5)
Cam.Z = h-5;
if (CamAngleY < -0.456f)
CamAngleY = -0.456f;

if (Cam.Y < (heightData[ (int)(Cam.X + w), terrainHeight - (int)(Cam.Z + h)] + CamHeight))
{
Cam.Y = (heightData[ (int)(Cam.X + w), terrainHeight - (int)(Cam.Z + h)] + CamHeight);
CamYSpd = 0;
}
else
Cam.Y -= CamYSpd;
if (Cam.Y > (heightData[ (int)(Cam.X + w), terrainHeight - (int)(Cam.Z + h)] + CamHeight)+5 && CamYSpd < 3)
CamYSpd += 0.05f;
if (keyState.IsKeyDown(Keys.Space) && Cam.Y < (heightData[ (int)(Cam.X + w), terrainHeight - (int)(Cam.Z + h)] + CamHeight) + 5)
CamYSpd = -1.5f;
if (keyState.IsKeyDown(Keys.W))
{
Cam.Z += (float)Math.Sin(CamAngleX) * 2.5f;
Cam.X += (float)Math.Cos(CamAngleX) * 2.5f;
}
if (keyState.IsKeyDown(Keys.S))
{
Cam.Z -= (float)Math.Sin(CamAngleX) * 2.5f;
Cam.X -= (float)Math.Cos(CamAngleX) * 2.5f;
}
if (keyState.IsKeyDown(Keys.D))
{
Cam.Z += (float)Math.Sin(CamAngleX - ((180 / Math.PI) * 90)) * 2.5f;
Cam.X += (float)Math.Cos(CamAngleX - ((180 / Math.PI) * 90)) * 2.5f;
}
if (keyState.IsKeyDown(Keys.A))
{
Cam.Z -= (float)Math.Sin(CamAngleX - ((180 / Math.PI) * 90)) * 2.5f;
Cam.X -= (float)Math.Cos(CamAngleX - ((180 / Math.PI) * 90)) * 2.5f;
}
if (keyState.IsKeyDown(Keys.Escape))
CaptureMouse = !CaptureMouse;
if (CaptureMouse)
{
CamAngleX += 0.05f * mx;
CamAngleY -= 0.05f * my;
Mouse.SetPosition(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2);
}
UpdateCamera();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

RasterizerState rs = new RasterizerState();
rs.CullMode = CullMode.CullCounterClockwiseFace;


device.RasterizerState = rs;
Matrix worldMatrix = Matrix.CreateTranslation(-terrainWidth / 2.0f, 0, terrainHeight / 2.0f) * Matrix.CreateRotationY(angle);
effect.CurrentTechnique = effect.Techniques["Colored"];
effect.Parameters["xView"].SetValue(viewMatrix);
effect.Parameters["xProjection"].SetValue(projectionMatrix);
effect.Parameters["xWorld"].SetValue(worldMatrix);
Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f);
lightDirection.Normalize();
effect.Parameters["xLightDirection"].SetValue(lightDirection);
effect.Parameters["xAmbient"].SetValue(0.1f);
effect.Parameters["xEnableLighting"].SetValue(true);
device.Indices = myIndexBuffer;
device.SetVertexBuffer(myVertexBuffer);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
spriteBatch.Begin();
spriteBatch.DrawString(DebugFont, "Position: " + Cam.X.ToString() + "," + Cam.Y.ToString() + "," + Cam.Z.ToString(), new Vector2(5, 5), Color.White);
spriteBatch.End();

base.Draw(gameTime);
}
}
}




Thanks in advance for any help.

Share this post


Link to post
Share on other sites
Advertisement

Problem is with depth, like if Im looking at a mountain the stuff behind it will be drawn on top of it.


Immediately - sounds like you don't have a depth buffer -or- its disabled. For future reference, typically posting an image of the problem is a good thing. But a quick scan through your code yielded the following:

-When you use your spritebatch, I notice you're not setting a DepthStencilState, by default spritebatch uses a DepthStencilState with DepthBufferEnable/DepthBufferWriteEnable set to false. And you're not setting a DepthStencilState that re-enables the depth buffer when you're drawing your terrain (just a rasterizerstate). A good rule of thumb is to "only set the states you need" before you draw anything. D3D is something like a state machine, so whatever renderstate you last set will remain active. So the spritebatch disabling the depth buffer at the end of your first draw call, the depth buffer will remain disabled at the beginning of the next draw call which would explain what you're seeing.

-I notice you set the preferred depthstencil format on the GraphicsDeviceManager in LoadContent...you -may- have to do this in Initialize, because I think the device is initialized (e.g. you set the backbuffer width/height in initialize) before LoadContent. But I'm not 100% positive when its initialized (it has to be before LoadContent, since you need the device to load shaders, textures, etc!); if you're changing presentation parameters after the first initialization, you have to reset the device.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!