0

The last few days we worked on our voxel engine. We get to some depth rendering problems if we draw our cubes. See following Youtube-Video: http://youtu.be/lNDAqO7yHBQ

We already searched along this problem and found different approaches but none of them solved our problem.

  • GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.CornflowerBlue, 1.0f, 0);
  • GraphicsDevice.BlendState = BlendState.Opaque;
  • GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  • GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

Our LoadContent() Method:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    _spriteBatch = new SpriteBatch(GraphicsDevice);

    // TODO: use this.Content to load your game content here
    _effect = new BasicEffect(GraphicsDevice);

    _vertexBuffer = new VertexBuffer(GraphicsDevice, Node.VertexPositionColorNormal.VertexDeclaration, _chunkManager.Vertices.Length, BufferUsage.WriteOnly);
    _vertexBuffer.SetData(_chunkManager.Vertices); // copies the data from our local vertices array into the memory on our graphics card

    _indexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), _chunkManager.Indices.Length, BufferUsage.WriteOnly);
    _indexBuffer.SetData(_chunkManager.Indices);
}

Our Draw() Method:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    GraphicsDevice.BlendState = BlendState.Opaque;
    GraphicsDevice.DepthStencilState = DepthStencilState.Default;
    GraphicsDevice.RasterizerState = RasterizerState.CullClockwise;

    // Set object and camera info
    //_effect.World = Matrix.Identity;
    _effect.View = _camera.View;
    _effect.Projection = _camera.Projection;
    _effect.VertexColorEnabled = true;
    _effect.EnableDefaultLighting();

    // Begin effect and draw for each pass
    foreach (var pass in _effect.CurrentTechnique.Passes)
    {
        pass.Apply();

        GraphicsDevice.SetVertexBuffer(_vertexBuffer);
        GraphicsDevice.Indices = _indexBuffer;

        GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _chunkManager.Vertices.Count(), 0, _chunkManager.Indices.Count() / 3);
    }

    base.Draw(gameTime);
}

Our View and Projection setup:

Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)Game.Window.ClientBounds.Width / Game.Window.ClientBounds.Height, 1, 500);
View = Matrix.CreateLookAt(CameraPosition, CameraPosition + _cameraDirection, _cameraUp);

We use the Camera (http://www.filedropper.com/camera_1) from Aaron Reed's book (http://shop.oreilly.com/product/0636920013709.do).

Did you see something we missed? Or do you have an idea to solve this problem?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Hayne
  • 1
  • 1

2 Answers2

0

Today we worked on this topic. The coordinates of the voxels in our original code were arround (X:600'000, Y:750, Z:196'000). After we relocated all voxels closer to the zero point (X:0, Y:0, Z:0) the described problem disappeared. We assume this has something to do with the datatyp float which is used by XNA. According to the MSDN (http://msdn.microsoft.com/en-us/library/b1e65aza.aspx) a float has only a precision of 7 digits. We concluded that if you put your voxels on coordinates with a precision of 7 digits and because the DepthBuffer from XNA works with floats you get the effect we described above.

Could maybe someone confirm our assumption?

Thank you!

Hayne
  • 1
  • 1
  • Well this might be correct. You could use double precision but i don't know if XNA supports it, if not you need to use OpenGL/DirectX directly or, as soon its released, Mantle. Try to stay below 99,999.99 and the prevision issues might disappear ( I didn't test it ) otherwise use doubles. – Felix K. Nov 30 '13 at 10:26
  • @hayne see my answer below –  Oct 12 '14 at 16:04
0

Yes it's a well-known problem in gaming, particularly large world simulations such as flight and space sims. Essentially as the camera moves too far away from the origin, floating point inaccuracies arise which play havoc, particularly during rotations.

The solution is a method known as floating origin where instead of moving the eye you essentially move the universe. This article is for Unity3D but since it is .net you can convert it to XNA. You can read more about it here in this excellent article

Also, there is only so much you can squeeze into a finite number of bits in a z-buffer whilst viewing the very close and the very far at the same time. For that you need you need to use a logarithmic z-buffer instead of 1:1. Want to know more?

I blogged about it some time back when I was working on my space sim here.