0

I'm creating an XNA game that creates random islands from multiple sprites. It creates them in a separate thread, then compiles them to a single texture using RenderTarget2D.

To create my RenderTarget2D I need a graphics device. If I use the automatically created graphics device, things work okay for the most part, except that draw calls in the main game thread conflict with it. Using lock() on the graphics device causes flickering, and even then the texture is sometimes not created properly.

If I create my own Graphics device, there are no conflicts but the islands never render correctly, instead coming out pure black and white. I have no idea why this happens. Basically I need a way to create a second graphics device that lets me get the same results, instead of the black / white. Anyone got any ideas?

Here's the code I'm using to try and create my second graphics device for exclusive use by the TextureBuilder:

var presParams = game.GraphicsDevice.PresentationParameters.Clone();
            // Configure parameters for secondary graphics device
            GraphicsDevice2 = new GraphicsDevice(game.GraphicsDevice.Adapter, GraphicsProfile.HiDef, presParams);

Here's the code I'm using to render my islands to a single texture:

public IslandTextureBuilder(List<obj_Island> islands, List<obj_IslandDecor> decorations, SeaGame game, Vector2 TL, Vector2 BR, int width, int height)
    {
        gDevice = game.Game.GraphicsDevice; //default graphics
        //gDevice = game.GraphicsDevice2 //created graphics

        render = new RenderTarget2D(gDevice, width, height, false, SurfaceFormat.Color, DepthFormat.None);

        this.islands = islands;
        this.decorations = decorations;
        this.game = game;

        this.width = width;
        this.height = height;

        this.TL = TL; //top left coordinate
        this.BR = BR; //bottom right coordinate
    }

    public Texture2D getTexture()
    {
        lock (gDevice)
        {
            //Set render target. Clear the screen.
            gDevice.SetRenderTarget(render);
            gDevice.Clear(Color.Transparent);

            //Point camera at the island
            Camera cam = new Camera(gDevice.Viewport);
            cam.Position = TL;
            cam.Update();

            //Draw all of the textures to render
            SpriteBatch batch = new SpriteBatch(gDevice);
            batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, cam.Transform);
            {
                foreach (obj_Island island in islands)
                {
                    island.Draw(batch);
                }
                foreach (obj_IslandDecor decor in decorations)
                {
                    decor.Draw(batch);
                }
            }
            batch.End();

            //Clear render target
            gDevice.SetRenderTarget(null);

            //Copy to texture2D for permanant storage
            Texture2D texture = new Texture2D(gDevice, render.Width, render.Height);
            Color[] color = new Color[render.Width * render.Height];
            render.GetData<Color>(color);
            texture.SetData<Color>(color);

            Console.WriteLine("done");

            return texture;
        }

Here's what should happen, with a transparent background (and usually does if I use the default device) http://i110.photobucket.com/albums/n81/taumonkey/GoodIsland.png

Here's happens when the default device conflicts and the main thread manages to call Clear() (even though it's locked too) NotSoGoodIsland.png (need 10 reputation....)

Here's what happens when I use my own Graphics device http://i110.photobucket.com/albums/n81/taumonkey/BadIsland.png

Thanks in advance for any help provided!

1 Answers1

0

I may have solved this by moving the RenderToTarget code into the Draw() method and calling it from within the main thread the first time Draw() is called.