Search code examples
c#xnaxna-4.0antialiasingrendertarget

Rendering to a non-null render tarhet in XNA disables antialiasing


I'm rendering a 3d model to a rendertarget2D, which I then draw to the screen using a sprite batch. I enabled antialiasing in my constructor using this line:

graphics.PreferMultiSampling = true;

When I was rendering the model directly to the backbuffer, the antialiasing worked as expected. Now that I'm rendering to a rendertarget2D the antialiasing no longer works and I get jagged edges. (I'm not resizing or rotating the rendertarget2D.)

Can sy pls explain this mystery for me?

Code:

public MyGame()
        {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        graphics.PreferredBackBufferHeight = 720;
        graphics.PreferredBackBufferWidth = 1208;
        graphics.PreparingDeviceSettings += setBackbufferPreserveContents;

        graphics.PreferMultiSampling = true;

        this.IsMouseVisible = true;
        this.Window.Title = "MyGame";

        graphics.ApplyChanges();
        }

public void setBackbufferPreserveContents(object sender, PreparingDeviceSettingsEventArgs e)
        {
        e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage = RenderTargetUsage.PreserveContents;
        }

protected override void Draw(GameTime gameTime)
        {
        GraphicsDevice.SetRenderTarget(BoardScreen);
        GraphicsDevice.Clear(Color.Transparent);
        Board.DrawMe(cam);

        GraphicsDevice.SetRenderTarget(null);
        GraphicsDevice.Clear(Color.CornflowerBlue);

        sb.Begin();
        sb.Draw((Texture2D)BoardScreen, new Rectangle(0, 0, 720, 720), Color.White);
        sb.End();

        base.Draw(gameTime);
        }

Board is of the class DrawableModel, which contains a model and the method DrawMe(Camera camera) which simply draws the model to the screen. Camera is a simple class containing the projection and view matrices, the position and the target positision of the camera.

Update:

Here's what the DrawMe method does:

public void DrawMe(Camera camera)
        {
        foreach (ModelMesh mesh in ModelToDraw.Meshes)
            {
            foreach (BasicEffect effect in mesh.Effects)
                {
                effect.EnableDefaultLighting();
                effect.PreferPerPixelLighting = true;

                effect.World = Matrix.CreateTranslation(Translation);
                effect.Projection = camera.Projection;
                effect.View = camera.View;
                }
            mesh.Draw();
            }
        }

Update 2:

Here's the rest of the functions in the main XNA file that I've done anything to (Update and UnloadContent are yet untouched.):

protected override void Initialize()
        {
        BoardScreen = new RenderTarget2D(graphics.GraphicsDevice, 720, 720);
        base.Initialize();
        }

    protected override void LoadContent()
        {
        sb = new SpriteBatch(GraphicsDevice);
        Board = new DrawableModel(Content.Load<Model>("Models/Board"), Vector3.Zero, Vector3.Zero, Vector3.One);
        }

Solution

  • Edit, updated:

    graphics.PreferMultiSampling only enables anti-aliasing on the back buffer. I think the problem might be that when drawing to your render target it isn't drawing there with anti-aliasing.

    The RenderTarget2D constructor has an overload that takes a preferredMultiSampleCount parameter. Try calling that and pass say 4 as the preferred multi sample count. If that works you might then be able to turn off multisampling on the back buffer.


    Old: I had the same problem as I was rendering in 3D to create non-square tiles out of polygons and then switching to SpriteBatch to draw in 2D*. The SpriteBatch.Begin() changes a whole bunch of render states under the cover, which will screw up subsequent (even next frame) 3D draws. So you need to reset these states before doing the 3D drawing.

    There's more detail here but IIRC there were more states I needed to change than that article mentions.

    Hopefully that's the problem anyway.

    *although anti-aliasing wasn't my problem, it was more severe it just wasn't drawing.

    edit: answer to a similar but not identical question that provides a longer list of the kind of stuff to try reseting