2
\$\begingroup\$

I've got a problem drawing a 3D model to a RenderTarget2D in XNA 4. When the model is drawn to a render target, and then the render target is later drawn to the screen it appears distorted. (See right image below)

However, if I draw directly to the backbuffer, then everything appears correctly (See left image)

I'm resetting all the states before doing the 3D drawing. (BlendState, DepthStencilState, SamplerStates and RasterizerState)

Example of problem

This is my draw method. I first draw to the render target. Then I use a spritebatch to draw this to the screen (offset to the right for this example). Finally yfor direct comparison I reset the states again and draw the 3d model a second time directly to the back buffer (using the exact same DrawModel() method) and it works fine.

    protected override void Draw(GameTime gameTime)
    {
        // First set to use a render target.
        GraphicsDevice.SetRenderTarget(_playerBufferRenderTarget);
        GraphicsDevice.Clear(Color.Black);

        // Reset all the states as appropriate for 3d drawing.
        GraphicsDevice.BlendState = BlendState.Opaque;
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
        GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

        // Draw the model (to the rendertarget)
        DrawModel();

        // Go back to the backbuffer.
        GraphicsDevice.SetRenderTarget(null);
        GraphicsDevice.Clear(Color.Black);

        // Now draw the rendertarget to the screen as a sprite (Offset to the right).
// (This looks wrong)
        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, null, null, null);
        spriteBatch.Draw(_playerBufferRenderTarget, new Vector2(300, 0), null, Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0);
        spriteBatch.End();

        // Again, reset the states.
        GraphicsDevice.BlendState = BlendState.Opaque;
        GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
        GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;

        // Now draw the model again, but this time directly to the back buffer.
// (This works).
        DrawModel();

        base.Draw(gameTime);
    }

I create the RenderTarger2D within the LoadContent() method.

_playerBufferRenderTarget = new RenderTarget2D(this.GraphicsDevice, 800, 500);

This is the DrawModel method for reference although this is basically copied directly from an MSDN sample:

    private void DrawModel()
    {
        Matrix[] transforms = new Matrix[_playerModel.Bones.Count];
        _playerModel.CopyAbsoluteBoneTransformsTo(transforms);

        foreach (ModelMesh mesh in _playerModel.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(modelRotation) * Matrix.CreateTranslation(modelPosition);
                effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);
                effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(90.0f), aspectRatio, 1.0f, 10000.0f);
            }

            mesh.Draw();
        }
    }

I've included a link to the Player.fbx model file. Is it possible that this could be caused by something I've done wrong when creating the model.

\$\endgroup\$
2
  • \$\begingroup\$ Looks like overdraw due to the lack of depth buffer. \$\endgroup\$
    – arul
    Commented Feb 26, 2012 at 20:34
  • \$\begingroup\$ @arul - Spot on. I changed my RenderTarget creation to specify DepthFormat.Depth24Stencil8 and it's working perfectly. (Post it as and answer and I'll accept it) \$\endgroup\$ Commented Feb 26, 2012 at 20:40

1 Answer 1

4
\$\begingroup\$

Looks like overdraw due to the lack of depth buffer.

You can specify the depth buffer when you create the RenderTarget2D:

 = new RenderTarget2D(this.GraphicsDevice, 800, 500, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);
\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .