使用 MatrixStack 在 Managed Direct3D 中渲染带有 Alpha 通道和颜色键透明度的纹理





5.00/5 (14投票s)
2005年6月28日
3分钟阅读

129283

2308
本文简要介绍了如何使用托管Direct3D在C#中借助MatrixStack将具有Alpha通道和透明关键色的纹理位图渲染到顶点。
引言
此示例说明了如何将具有Alpha通道或关键颜色透明度的位图纹理文件映射到C#中的托管Direct3D顶点缓冲区。在此示例中,.png、.bmp和.jpg文件提供纹理。
DirectX MatrixStack
类还用于创建三个纹理顶点平面的简单分层“场景”,每个平面的位置都取决于前一个平面。这种变换的“堆叠”对于创建3D用户界面、机器人手臂式运动很有用,或者可以用于任何一个对象位置依赖于另一个对象位置的情况。
纹理映射的工作原理
要渲染纹理位图,有两个关键的映射或“变换”步骤。第一步将加载的纹理坐标映射到存储在顶点缓冲区中的一组顶点坐标。第二步将顶点缓冲区局部坐标映射到最终窗口坐标。在示例中,顶点只是形成正方形平面的两个三角形条带,正方形位图纹理映射到该平面。
顶点到窗口坐标的变换是通过Direct3D设备在渲染时内部执行的矩阵乘法来完成的。另一种考虑变换的方法是将其视为“依赖关系”,其中局部位置“依赖”于世界位置,而世界位置又“依赖”于视图位置,依此类推。
可以使用MatrixStack
类“堆叠”(相乘)局部顶点矩阵,使一个对象的位置依赖于另一个对象的位置。直观地说,每次拖动父窗口并且子窗口随之移动时,在2D中都会发生这种情况。类似地,矩阵堆栈可用于创建3D窗口系统,方法是在遍历期间从已压入和弹出堆栈的树中处理此依赖链。
运行示例
此代码使用托管DirectX 9程序集,因此需要将它们安装到搜索路径中。托管DirectX的一个优点是程序集DLL可以简单地复制到EXE目录。
要运行演示,请解压缩Zip文件并运行3DAlphaTransparency.exe。从解决方案构建源代码时,可执行程序集将放置在“BinariesAndBitmaps/”子目录中。三个示例位图路径硬编码在C#MainForm
中,位图位于与3DAlphaTransparency.exe相同的目录中。
C#源代码说明
主要有两个类:MainForm
和TDPanel
。TDPanel
创建一个可见的纹理和顶点缓冲区,MainForm
实例化三个TDPanel
对象,将它们存储在ArrayList中,并使用MatrixStack
和Direct3D设备将它们渲染到MainForm
窗口。
配置设备以进行Alpha混合
在设备重置时在MainForm
中启用Alpha混合。
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;
...
}
使用透明关键颜色加载纹理
TDPanel
使用TextureLoader
加载纹理,任何具有品红色像素的位图都将被渲染为透明的。
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());
}
将纹理映射到两个三角形条带
然后使用PositionTextured
格式将位图纹理(u,v)的角映射到形成局部坐标中正方形的两个三角形条带的顶点。
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();
}
使用MatrixStack类进行渲染
MainForm
创建三个TDPanel
对象并将它们存储在ArrayList
中。MainForm
还通过创建MatrixStack
,循环遍历TDPanel
,并将世界矩阵和顶点信息发送到设备进行渲染来执行渲染。
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);
}
}
更多创意
Alpha通道、透明度和矩阵堆栈的使用可以扩展到创建自定义用户界面和控件。托管Direct3D仅用几行代码即可提供许多功能强大且高级的渲染功能,其可视化可能性仅受想象力限制!
历史
这是我第一次向Code Project提交文章。我喜欢阅读许多文章,期待阅读您的反馈。