上一次我们在Managed DirectX世界里接触到了Direct3D设备的概念,它是Direct3D中几乎所有功能的开始。从这次我要开始在DirectX中绘出3D图形了。3D图形常常用一组包围形状表面的多边形来表示,无论形状多么复杂,我们都可以用一定数目的多边形来逼近。目前用于游戏的显卡多使用三角形网格系统,即用一系列三角形来表示物体的表面。在电影级渲染中,还常常用到四边形网格。关于网格(mesh)这个重要的概念以后还会遇到,这次我将学习如何绘制三角形。
Direct3D支持的图元(Primitive)类型有点、线段、线条、三角、成片三角和三角扇形等。要绘制图元,必须将点集载入到数据流中。顶点缓冲区(Vertex Buffer)即是DirectX保存顶点数据的常用方式。在顶点缓冲区内我们可以对顶点进行各种操作,比如坐标变换、光照等。Direct3D支持灵活顶点格式(FVF),用户可以自行决定在一个顶点数据中包含那些数据,比如顶点的坐标、颜色、法向量等。可以自由搭配各种属性,以至于我们可用自定义的结构体来保存顶点数据。这次我选择的是一种已经预定义在DirectX类库中的类型:CustomVertex::TransformedColored。它包含顶点的坐标、经变换后的坐标以及顶点的漫反射颜色。
创建顶点缓冲区需要使用VertexBuffer类。要定义一个顶点缓冲区,需要下列参数:顶点的结构体类型、个数、设备、顶点缓冲区属性、顶点格式和顶点缓冲区的资源位置。顶点的结构体类型是一个System::Type类型参数(主要是获取顶点结构体的内存大小)。顶点缓冲区属性可以是Usage枚举中的任意值的组合,我这次就用None。顶点格式是对于灵活顶点格式的描述,必须准确指出顶点结构体中包含哪些数据。最后一个顶点缓冲区的资源位置表示将顶点缓冲区置于内存还是显存中。基于这些设置,就可以写出一个初始化顶点缓冲区的函数:
//顶点缓冲区全局对象
static VertexBuffer^ vb;
static Boolean InitializeVertexBuffer()
{
//初始化一个三角形的顶点数组
array<CustomVertex::TransformedColored>
gcnew array<CustomVertex::TransformedColored>
vertices[0] = CustomVertex::TransformedColored(150.0, 50.0, 0.5, 1.0, 0xffffff00);
vertices[1] = CustomVertex::TransformedColored(250.0, 250.0, 0.5, 1.0, 0xff00ff00);
vertices[2] = CustomVertex::TransformedColored(50.0, 250.0, 0.5, 1.0, 0xff0000ff);
try
{
//创建顶点缓冲区
vb = gcnew VertexBuffer(
typeid<CustomVertex::TransformedColored>
d3dDevice, /* 要使用的Direct3D设备 */
Usage::None, /* 顶点缓冲区属性 */
CustomVertex::TransformedColored::Format, /* 灵活顶点格式 */
Pool::Default /* 顶点缓冲区资源位置,这里选择显存 */
);
//填充顶点缓冲区
GraphicsStream^ gs = vb->Lock(0, 0, LockFlags::None);
gs->Write(vertices);
vb->Unlock();
return true;
}
catch(DirectXException^)
{
return false;
}
}
别忘了在CleanUp方法中清理使用过的VertexBuffer对象。接下来,我们需要在渲染函数中增加绘制图元的代码。注意:这些代码一定要放在对设备BeginScene函数和EndScene函数的调用之间,否则就会出错。
d3dDevice->SetStreamSource(0, vb, 0);
d3dDevice->VertexFormat = CustomVertex::TransformedColored::Format;
d3dDevice->DrawPrimitives(PrimitiveType::TriangleList, 0, 1);
最后,我们只要在main函数中添加调用创建顶点缓冲区函数的代码即可:
int Main()
{
TestMDXForm^ f = gcnew TestMDXForm();
if (DirectXProgram::InitializeDirect3D(f) &&
DirectXProgram::InitializeVertexBuffer())
{
//显示窗口
f->Show();
Application::DoEvents();
Application::Run();
}
return 0;
}
其他的代码与上次的项目完全相同。运行看看绘制出来的效果吧:
打印 | 张贴于 2004-10-31 22:23:00 | Tag:技术随笔 Managed DirectX学习笔记
留言反馈
加油啊
顺便说一句:
是不是VB的很重要吗? ;)
呵呵
不解不解
效果很想,但我的程序结构更像本地版DX的,而且是C++/CLI的,你都没处去找呢,呵呵。
我也要想赞啊...只是觉得光说空话比较不好 :p