Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to draw an object composited by two cubes (A & B) (one on top of the other, but for now I have them a little bit more open). I am able to do it and this is the result.

enter image description here (Cube A is the blue and Cube B is the one with brown text that comes from a png texture)

But I want to have any text as parameter in the cube B. I have tried what @alecnash suggested in his question, but for some reason when I try to draw cube B, cube A dissapears and everything turns purple.

enter image description here

This is my draw code:

public void Draw(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, Matrix viewMatrix, Matrix projectionMatrix)
        {
            graphicsDevice.BlendState = BlendState.Opaque;
            graphicsDevice.DepthStencilState = DepthStencilState.Default;
            graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
            graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;


            // CUBE A
            basicEffect.View = viewMatrix;
            basicEffect.Projection = projectionMatrix;
            basicEffect.World = Matrix.CreateTranslation(ModelPosition);
            basicEffect.VertexColorEnabled = true;
            foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                drawCUBE_TOP(graphicsDevice);
                drawCUBE_Floor(graphicsDevice);
                DrawFullSquareStripesFront(graphicsDevice, _numStrips, Color.Red, Color.Blue, _levelPercentage);
                DrawFullSquareStripesLeft(graphicsDevice, _numStrips, Color.Red, Color.Blue, _levelPercentage);
                DrawFullSquareStripesRight(graphicsDevice, _numStrips, Color.Red, Color.Blue, _levelPercentage);
                DrawFullSquareStripesBack(graphicsDevice, _numStrips, Color.Red, Color.Blue, _levelPercentage);

            }

            // CUBE B
            // Set the World matrix which defines the position of the cube
            texturedCubeEffect.World = Matrix.CreateTranslation(ModelPosition);
            // Set the View matrix which defines the camera and what it's looking at
            texturedCubeEffect.View = viewMatrix;
            // Set the Projection matrix which defines how we see the scene (Field of view)
            texturedCubeEffect.Projection = projectionMatrix;
            // Enable textures on the Cube Effect. this is necessary to texture the model
            texturedCubeEffect.TextureEnabled = true;
            Texture2D a = SpriteFontTextToTexture(graphicsDevice, spriteBatch, arialFont, "TEST ", Color.Black, Color.GhostWhite);
            texturedCubeEffect.Texture = a;
            //texturedCubeEffect.Texture = cubeTexture;
            // Enable some pretty lights
            texturedCubeEffect.EnableDefaultLighting();
            // apply the effect and render the cube
            foreach (EffectPass pass in texturedCubeEffect.CurrentTechnique.Passes)
            {
                pass.Apply();
                cubeToDraw.RenderToDevice(graphicsDevice);
            }


        }

    private Texture2D SpriteFontTextToTexture(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, SpriteFont font, string text, Color backgroundColor, Color textColor)
    {
        Vector2 Size = font.MeasureString(text);
        RenderTarget2D renderTarget = new RenderTarget2D(graphicsDevice, (int)Size.X, (int)Size.Y);
        graphicsDevice.SetRenderTarget(renderTarget);

        graphicsDevice.Clear(Color.Transparent);

        spriteBatch.Begin();
        //have to redo the ColorTexture
        //spriteBatch.Draw(ColorTexture.Create(graphicsDevice, 1024, 1024, backgroundColor), Vector2.Zero, Color.White);

        spriteBatch.DrawString(font, text, Vector2.Zero, textColor);
        spriteBatch.End();

        graphicsDevice.SetRenderTarget(null);

        return renderTarget;
    }

The way I generate texture with dynamic text is:

 Texture2D a = SpriteFontTextToTexture(graphicsDevice, spriteBatch, arialFont, "TEST ", Color.Black, Color.GhostWhite);

After commenting several parts to see what caused the problem, it seems to be located in this line

graphicsDevice.SetRenderTarget(renderTarget);
share|improve this question
    
I have commented the line in SpriteFontTextToTexture because it is killing my fps and makes no cube appear in screen. –  cad Nov 25 '12 at 17:25

1 Answer 1

up vote 1 down vote accepted

That purple colour is the "uninitialized surface" colour.

Basically whenever you call GraphicsDevice.SetRenderTarget, the render target that you set gets cleared (by default). In this case, the back-buffer counts as a render target (setting null).

You could set RenderTargetUsage.PreserveContents on the backbuffer. But preserving the contents of a render target is slow on Xbox 360 and Windows Phone. The default is to clear in order to be fast on those devices (and Windows matches that behaviour to make your life easier when porting).

The recommended way to solve this is to order your drawing so that you fill your render targets before you draw anything to the backbuffer.

This is explained in detail in this blog post. And also in my answer here.


Also it looks like you are creating a fresh render-target each frame. That's a big no-no. Create it once and re-use it!

share|improve this answer
    
I've tried quickly to use PreserveContents (as I am doing my project in windows) by changing declaration of rendertarget with RenderTarget2D renderTarget = new RenderTarget2D(graphicsDevice, (int)Size.X, (int)Size.Y,false,SurfaceFormat.Color,DepthFormat.None,1,RenderTargetUsage.Prese‌​rveContents); and doesn't seem to work. This night I will read deeply the blog post... –  cad Nov 26 '12 at 6:49
1  
@cad The target you need to be preserving is the backbuffer itself. When you call SetRenderTarget(null) you are clearing it. You have to mess around with PreparingDeviceSettings to make this change. –  Andrew Russell Nov 26 '12 at 8:38
    
I've changed the order as you suggested and draw first cube B and later cube A. It worked :) Also did as you suggested and only create render targer once with this: if (renderTarget==null) { renderTarget = new RenderTarget2D(graphicsDevice, (int)Size.X, (int)Size.Y, false, SurfaceFormat.Color, DepthFormat.None, 1, RenderTargetUsage.PreserveContents); } –  cad Dec 1 '12 at 15:46

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.