Managed DirectX First Steps: Direct 3D Basics and DirectX vs. GDI+ - Fourth Step: Using Transparent Textures
(Page 11 of 14 )
You’ll use the same code employed for the windowed mode test as the basis for your transparency test. You’ll still have the walking man as a background texture, and will load another texture over it, with a color set to transparent, so you can see the man running behind parts of it.
For this purpose, create a window drawing and fill the panes and surrounding areas with blue color, as shown in Figure 3-27.

Figure 3-27. A window, with a flat blue color to be used as a transparent texture
Follow these steps for including your new transparent texture in the sample:
- In the InitD3D routine, set the device parameters to indicate that you’ll be using transparent textures.
- Create a new function that will load the transparent texture.
- Create a function to generate a new square in which you’ll render the transparent texture.
- Change the click button event in the main window to call this function.
- Adjust the Render procedure to show the transparent texture.
- As defined in the game project, you must call the function that creates the square on the MouseMove event of the test window, so you can move the square with the transparent texture to different parts of the window and see the resulting effects.
Let’s start with the InitD3D function. All you need to do is to set three new parameters of the device.
device.RenderState.SourceBlend = Blend.SourceAlpha; device.RenderState.DestinationBlend = Blend.InvSourceAlpha; device.RenderState.AlphaBlendEnable = true;
These parameters tell how the rendering must blend together the source and the destination bitmaps to achieve the final transparency effect, and the last one informs the device where you want the blending to occur. The parameters shown in the preceding code must apply to almost all cases, and will be used throughout the rest of this book.
Please note that the blending operation slows performance, so in your real games you’d only set the AlphaBlendEnable property to True just before drawing the transparent textures, and reset it after finishing them. Because this is a test, just leave it set all the time—performance isn’t your preoccupation here.
The function for loading the transparent texture is slightly different from the one you saw in the previous samples, as you can see in the next code piece, which needs to be included in the CreateTextures procedure to add transparency support:
// You will use blue as the transparent color.
Color colorKeyVal = Color.FromArgb(255, 0, 0, 255);
// Load the transparent texture.
TranspTexture = TextureLoader.FromFile(device,
Application.StartupPath +
@"\TranspSample.bmp", 64, 64, D3DX.Default, 0,
Format.Unknown, Pool.Managed,
Filter.Point, Filter.Point, colorKeyVal.ToArgb());
Well, okay, this is VERY different. Although you can load an opaque texture specifying only the device and the filename, the overloaded version of the function to load transparent textures will have a lot more features and flexibility (but it’ll have worse performance, too). We won’t enter into the details about every parameter, because we won’t use most of them in this book. All you need to know for now is the following:
- The 64, 64 parameters represent the width and height of the texture being loaded. These must be values supported by the device, usually a power of 2 (16, 32, 64, 128, and so on, with some new boards going up to 4096). These values are automatically calculated in the simpler version of the function.
- The filter parameters presented here are the best performing ones. If you want a little more quality, you can change them from Filter.Point to Filter.Default.
- The ColorKey parameter receives the color that will be transparent. In this case, the alpha component of the color is significant: If you are loading images from file formats that don’t support transparency (such as bitmaps), this value will be always 255 (opaque).
The next step is to create a new square to load your transparent texture into. You can copy the functions used in the first sample, and adapt them to receive the x and y coordinates for the texture. Remember, you’ll move the texture with the mouse, and the only way to do it (for now, because we haven’t discussed transformation matrices yet) is updating the vertex positions, one by one.
public bool CreateTransparentVertices(float x, float
y) {
CustomVertex[] verts;
try {
// If the vertex buffer was previously created,
dispose them.
if(TranspVertBuffer != null) TranspVertBuffer.Dispose
();
TranspVertBuffer = new VertexBuffer(typeof
(CustomVertex),
numVerts, device, Usage.WriteOnly,
customVertexFlags, Pool.Default);
verts = TranspVertBuffer.Lock(0, 0) as CustomVertex
[];
TranspVertices(x, y, verts);
TranspVertBuffer.Unlock();
return true;
}
catch {
return false;
}
}
private void TranspVertices(float X, float Y, CustomVertex
[] vertices) {
// Create a square, composed of 2 triangles.
//Our transparent texture is 42 pixels wide and 60
long.
vertices[0] = CreateFlexVertex(X, Y, 0, 1, 0, 0);
vertices[1] = CreateFlexVertex(X + 42, Y, 0, 1, 1, 0); vertices[2] = CreateFlexVertex(X, Y + 60, 0, 1, 0, 1);
vertices[3] = CreateFlexVertex(X + 42, Y + 60, 0, 1, 1,
1);
}
To adjust the click event for the button on the main form, all you need to do is call the preceding function, passing a default position for the transparent window. The full procedure for the Click button is as follows:
using (TransparentTest transparentTest = new
TransparentTest()) {
transparentTest.Show();
// Initialize Direct3D and the Device object.
if(!transparentTest.InitD3D(transparentTest.Handle))
{
MessageBox.Show("Could not initialize Direct3D.");
transparentTest.Dispose();
return;
}
else {
// Load the textures and create the square to show
them.
if(!(transparentTest.CreateTextures() &&
transparentTest.CreateTransparentVertices(0,
0)))
{
MessageBox.Show("Could not initialize vertices
and textures.");
transparentTest.DisposeD3D();
transparentTest.Dispose();
return;
}
}
// If you have no errors, then enter the rendering loop.
while(!transparentTest.EndTest) {
transparentTest.Render();
// Frame rate calculation.
transparentTest.Text =
"Transparency Test. Frame rate " +
DirectXLists.CalcFrameRate().ToString
Application.DoEvents();
}
}
Adjusting the rendering function is just as easy, as there’s no difference in the rendering when displaying a simple texture or a transparent one. You can just add the following lines of code in the Render procedure, just below the lines that draw your walking man:
device.SetStreamSource(0, vertBuffer, 0); device.DrawPrimitives(PrimitiveType.TriangleStrip, 0,
numVerts - 2);
device.SetTexture(0, TranspTexture);
device.SetStreamSource(0, TranspVertBuffer, 0); device.DrawPrimitives(PrimitiveType.TriangleStrip, 0,
numVerts - 2);
Because the background of your transparent bitmap is blue, maybe it’s a good idea to change the window background to black, just to create a different look from the previous samples. You can do this by simply adjusting the call to the Clear method of the Device object to:
device.Clear(ClearFlags.Target, Color.Blue, 1.0F, 0);
All you need to do now is code the MouseMove event to call CreateTranspVertices. Because you receive the mouse x and y positions as arguments on the event, all you need is this code:
private void TransparentTest_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e) {
CreateTransparentVertices(e.X, e.Y);
}
And that’s it. Running your sample will allow you to test your transparent window by moving it with the mouse over the walking man, as shown in Figure 3-28.

Figure 3-28. Testing the transparent window
This chapter is from Beginning .NET Game Programming in C# by David Weller et. al.(Apress, 2004, ISBN: 1590593197). Check it out at your favorite bookstore today. Buy this book now.
|
Next: Fifth Step: Changing Diffuse Colors >>
More ASP.NET Articles
More By Apress Publishing