Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Rendering Textures with Alpha Channels and Color Key Transparency using a MatrixStack in Managed Direct3D

0.00/5 (No votes)
28 Jun 2005 1  
This brief article describes how to use managed Direct3D to render texture bitmaps with alpha channels and transparency key colours onto vertices in C# with the aid of a MatrixStack.

Sample Image - 3DAlphaTransparency.jpg

Introduction

This example illustrates how bitmap texture files with an alpha channel or a key color transparency can be mapped onto managed Direct3D vertex buffers in C#. In this example, .png, .bmp, and .jpg files provide the textures.

The DirectX MatrixStack class is also used to create a simple hierarchical "scene" of the three textured vertex planes, each having its position dependent on the previous one. This "stacking" of transformations is useful for creating 3D user interfaces, robot-arm type movements, or can be used anywhere where one object location depends on another.

How the Texture Mapping Works

To render a texture bitmap, there are two key mapping or "transform" steps. The first step maps the loaded texture coordinates to a set of vertex coordinates stored in a vertex buffer. The second step maps the vertex buffer local coordinates to the final window coordinates. In the sample the vertices are simply two triangle strips that form a square plane onto which the square bitmap textures are mapped.

The transformation of vertex to window coordinates is performed by matrix multiplications that the Direct3D device performs internally when rendering. Another way to think of transforms are as "dependencies", where the local position "depends" on the world position which in turn "depends" on the view position and so on.

Local vertex matrices can be "stacked" (multiplied) using the MatrixStack class to have the position of one object depend on the position of the other. Intuitively, this happens in 2D every time a parent window is dragged and the child moves with it. Similarly, matrix stacks can be used to create 3D windowing systems by processing this chain of dependencies from a tree that has been pushed and popped from the stack during traversal.

Running the Sample

This code uses the managed DirectX 9 assemblies, so they need to be installed in the search path. A nice feature of managed DirectX is that assembly DLLs can be simply copied into the EXE directory.

To run the demo, unpack the Zip and run 3DAlphaTransparency.exe. When building the source from the solution, the executable assembly will be placed in the "BinariesAndBitmaps/" subdirectory. Three sample bitmap paths are hard coded inside the C# MainForm, and the bitmaps are located in the same directory as the 3DAlphaTransparency.exe.

Explanation of the C# Source Code

There are two main classes: the MainForm, and the TDPanel. The TDPanel creates a single visible texture and vertex buffer, and the MainForm instantiates three TDPanel objects, stores them in an array list, and renders them using the MatrixStack and Direct3D Device onto the MainForm window.

Configuring the Device for Alpha Blending

Alpha blending is enabled in MainForm on device reset:

public void OnResetDevice(object sender, EventArgs e)
{
    ...
    //Enable alpha blending in the device

    device.RenderState.SourceBlend = Direct3D.Blend.SourceAlpha;
    device.RenderState.DestinationBlend = Direct3D.Blend.InvSourceAlpha;
    device.RenderState.AlphaBlendEnable = true;
    ...
}

Loading the Textures with a Transparency Key Color

The TDPanel loads in the texture using the TextureLoader, and a bitmap with any magenta colored pixels will be rendered as transparent:

public void CreateVertexBuffer()
{
    //load the bitmap file, and use Magenta as the color key

    PanelTexture = Direct3D.TextureLoader.FromFile(   
                         TDDevice, 
                         TextureFile,
                         0, 
                         0,
                         1,
                         Direct3D.Usage.None,
                         Direct3D.Format.Unknown,
                         Direct3D.Pool.Managed,
                         Direct3D.Filter.None,
                         Direct3D.Filter.None,
                         System.Drawing.Color.Magenta.ToArgb());
}

Mapping the Texture to Two Triangle Strips

The corners of bitmap texture (u,v) are then mapped onto the vertices of the two triangle strips that form a square in local coordinates, using the PositionTextured format:

public void OnCreateVertexBuffer(object sender, EventArgs e)
{
    Direct3D.CustomVertex.PositionTextured[] verts = 
             (Direct3D.CustomVertex.PositionTextured[])vb.Lock(0,0); 
    verts[0].X=-1.0f; verts[0].Y=-1.0f;
    verts[0].Z=0.0f; verts[0].Tu = 0.0f; verts[0].Tv=0.0f; 

    verts[1].X=-1.0f; verts[1].Y=1.0f ; verts[1].Z=0.0f; 
    verts[1].Tu = 1.0f; verts[1].Tv=0.0f;

    verts[2].X=1.0f; verts[2].Y=-1.0f; verts[2].Z=0.0f;
    verts[2].Tu = 0.0f; verts[2].Tv=1.0f;

    verts[3].X=1.0f; verts[3].Y=1.0f; verts[3].Z=0.0f;
    verts[3].Tu = 1.0f; verts[3].Tv=1.0f;
    vb.Unlock();
}

Rendering using the MatrixStack Class

The MainForm creates three TDPanel objects and stores them in an ArrayList. The MainForm also performs the rendering by creating the MatrixStack, looping through the TDPanels, and sending the world matrix and vertex information to the device to render:

private void Render()
{
    DirectX.MatrixStack matrixStack = new DirectX.MatrixStack();   
    // loop through the entire list of panels and render them  

    foreach(TDPanel tdPanel in panelList)   
    {  
        //set up the correct Texture attributes for  

        //correct handling of the alpha channel textures 

        this.device.SetTexture(0,tdPanel.PanelTexture);  
        this.device.VertexFormat = Direct3D.CustomVertex.PositionTextured.Format;
        this.device.SetStreamSource(0, tdPanel.PanelVertexBuffer, 0);
 
        //push the matrix for this panel onto the stack 

        matrixStack.Push();
        //Rotate this bitmap

        tdPanel.RotateMatrixTimer();
        //compute this bitmaps Local Matrix on the stack, and draw it

        matrixStack.MultiplyMatrixLocal(tdPanel.LocalMatrix);
        this.device.Transform.World = matrixStack.Top;
        //Each panel consists of two triangles

       this.device.DrawPrimitives(Direct3D.PrimitiveType.TriangleStrip, 0, 2);  
    }
}

Further Creative Ideas

The use of alpha channels, transparency, and matrix stacks can be extended to create custom user interfaces and controls. Managed Direct3D provides a host of very powerful and high level rendering capabilities with just a few lines of code, and the visualization possibilities are only limited by imagination!

History

This is my very first submission to The Code Project. I enjoy reading many of the articles, and I look forward to reading your feedback.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here