Microsoft Developer Network > Forums Home > Archived Forums Forums > XNA Game Studio Express > How can I draw a flat Sprite in 3D space using transparency/alpha layers?

Locked How can I draw a flat Sprite in 3D space using transparency/alpha layers?

  • Saturday, March 03, 2007 10:49 PM
     
     
    Hello XNA community,

    I am currently working on a level editor that renders in 3D for a 2D game (think New Super Mario Bros). I am using DrawIndexedPrimitives with 24 vertices to draw cubes, wedges, and other simple shapes that make up individual tiles in the game. When I use a similar technique to draw a 2D sprite in 3D space (let's say, a PNG file with transparent space in some areas of the file), the transparent parts of the image file end up being a dull ugly white color when pasted onto an indexed primitive in 3D space. How would I be able to draw these in 3D space with transparent elements (for effects like grass, trees, mountains, etc)?

    Please note that I do know how to use a SpriteBatch to draw 2D elements in 2D space. Once again, I am trying to draw 2D elements in 3D space. Also, at this time, making sure the 2D object remains looking directly at the camera is not that much of a concern as the camera never rotates in the game, it only zooms/translates.

    Thanks!!!

     - Nate Burba

Answers

  • Sunday, March 04, 2007 11:24 PM
     
     Answered
    These are the default values I use for standard alpha blending:

                //  enable alpha blending
                device.RenderState.AlphaBlendEnable = true;
                device.RenderState.SourceBlend = Blend.SourceAlpha;
                device.RenderState.AlphaSourceBlend = Blend.One;
                device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
                device.RenderState.BlendFunction = BlendFunction.Add;
                device.RenderState.AlphaDestinationBlend = Blend.InverseSourceAlpha;

                //  don't write z depth if there is no alpha
                device.RenderState.AlphaTestEnable = true;
                device.RenderState.AlphaFunction = CompareFunction.Greater;
                device.RenderState.ReferenceAlpha = 0;

All Replies

  • Saturday, March 03, 2007 11:25 PM
     
     

    Before you draw, make sure you're setting these render states:

    graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;

    graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;

    graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceApha;

  • Sunday, March 04, 2007 6:03 PM
     
     
    Hmm, when I use these two together:

    graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
    graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceApha;

    nothing draws at all.

    However, when I say:

    graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
    graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.SourceColor;

    I get transparent and non-transparent parts, but the non-transparent parts blend with anything in the background, instead of draw over them.

  • Sunday, March 04, 2007 6:28 PM
     
     
    Okay, so, it looks like its reading the entire thing as Alpha. That is why nothing draws. Doing the following blends the entire texture:

    RenderState.SourceBlend = Blend.InverseSourceColor;
    RenderState.DestinationBlend = Blend.SourceColor;

    I'm using PNG images, maybe I should try a TGA with an alpha channel?
  • Sunday, March 04, 2007 8:59 PM
     
     
    Using 4 vertices and a TGA with an alpha channel this still doesn't work. It looks like XNA is not reading the texture in properly (FYI, I am loading textures into Texture2D objects using content.Load() ). XNA simply doesn't see the alpha channel. It considers any transparency to be white. This files (both the TGA and the PNG) work with SpriteBatch though.
  • Sunday, March 04, 2007 11:24 PM
     
     Answered
    These are the default values I use for standard alpha blending:

                //  enable alpha blending
                device.RenderState.AlphaBlendEnable = true;
                device.RenderState.SourceBlend = Blend.SourceAlpha;
                device.RenderState.AlphaSourceBlend = Blend.One;
                device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
                device.RenderState.BlendFunction = BlendFunction.Add;
                device.RenderState.AlphaDestinationBlend = Blend.InverseSourceAlpha;

                //  don't write z depth if there is no alpha
                device.RenderState.AlphaTestEnable = true;
                device.RenderState.AlphaFunction = CompareFunction.Greater;
                device.RenderState.ReferenceAlpha = 0;

  • Monday, March 05, 2007 7:13 AM
     
     
    Okay, I tried this and nothing draws, once again.

    If I change the AlphaFunction to CompareFunction.LessEqual and I change Blend.InverseSourceAlpha to Blend.InverseSourceColor  and Blend.SourceAlpha to Blend.InverseSourceColor then I at least get something on the screen....

    Anyway, I think XNA can't see the alpha channel in the TGA file or the transparent pixels in the PNG file (even though it sees them just fine with SpriteBatch). This is why it draws "nothing".

    Does anyone have any demo's online using 2D "black face culled" or "alpha tested" sprites in a 3D world tested for depth? This is something that has been oddly absent in all of the demos/tutorials I've looked through.

    Thanks again for the help.

     - Nate
  • Monday, March 05, 2007 3:28 PM
     
     
    If drawing using SpriteBatch works, then your texture must contain the right data, so this must be something wrong you are doing in your drawing code.

    What pixel shader are you using to draw these polygons?
  • Monday, March 05, 2007 5:18 PM
     
     
    The code I posted above contains the correct settings for those render states.  Your problem lies somewhere else.  Can you post your simplest demo code, or at least your Matrix parameters and your shader code?
  • Sunday, March 11, 2007 5:53 PM
     
     
    I got it to work!!!

    I was using a BasicEffect and I had to change effect.VertexColorEnabled to false when drawing the sprites.

    Thank you so much for the help!!

     - Nate