XNA体素引擎中深度渲染的问题

时间:2012-10-02 09:31:14

标签: c# xna depth voxel

最近几天我们在我们的体素引擎上工作了。如果我们绘制立方体,我们会遇到一些深度渲染问题。请参阅以下Youtube-Video:http://youtu.be/lNDAqO7yHBQ

我们已经搜索过这个问题并找到了不同的方法,但没有一个解决了我们的问题。

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

我们的LoadContent()方法:

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);
}

我们的Draw()方法:

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);
}

我们的观看和投影设置:

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

我们使用Aaron Reed的书(http://www.filedropper.com/camera_1)中的相机(http://shop.oreilly.com/product/0636920013709.do)。

你有没有看到我们错过的东西?或者你有想法解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

今天我们就这个话题进行了研究。我们原始代码中体素的坐标是arround(X:600'000,Y:750,Z:196'000)。在我们将所有体素重新定位到更接近零点(X:0,Y:0,Z:0)之后,所述问题消失了。我们假设这与XNA使用的datatyp float有关。根据MSDN(http://msdn.microsoft.com/en-us/library/b1e65aza.aspx),浮点数的精度只有7位数。我们的结论是,如果你将体素放在坐标上,精度为7位,并且因为XNA的DepthBuffer与浮点数一起工作,你就会得到我们上面描述的效果。

也许有人会证实我们的假设吗?

谢谢!

答案 1 :(得分:0)

是的,这是游戏中众所周知的问题,特别是大型世界模拟,如飞行和太空模拟。基本上当相机移动距离原点太远时,出现浮点不准确性,这会造成严重破坏,特别是在旋转期间。

解决方案是一种称为floating origin的方法,而不是移动眼睛,而是基本上移动宇宙。本文适用于Unity3D,但由于它是.net,您可以将其转换为XNA。您可以阅读更多相关信息 here in this excellent article

此外,只有在z-buffer中可以挤入有限数量的位,同时在非常接近和非常远的同时观看。为此,您需要使用对数z缓冲区而不是1:1。 Want to know more?

blogged关于我在我的太空漫画here上工作的时间。{/ p>