用 Direct3D 编写的应用程序使用顶点来绘制几何形状。 每个三维 (3D) 场景都包括一个或多个这些几何形状。 Vertices 示例项目创建最简单的形状,一个三角形,并将其渲染到显示器上。
本教程展示了如何使用顶点创建三角形,步骤如下:
步骤
- 第 1 步 - 定义自定义顶点类型
- 第 2 步 - 设置顶点缓冲区
- 第 3 步 - 渲染显示
笔记 |
---|
Vertices 示例项目的路径是: Vertices 项目中的示例代码与 CreateDevice 项目中的示例代码几乎相同。 渲染顶点教程仅关注顶点特有的代码,不包括初始化 Direct3D、处理 Windows 消息、渲染或关闭。 |
第 1 步 - 定义自定义顶点类型
Vertices 示例项目使用三个顶点来渲染一个 2D 三角形。 这就引入了顶点缓冲区的概念,它是一个用于存储和渲染顶点的 Direct3D 对象。 通过指定自定义顶点结构和相应的自定义灵活顶点格式 (FVF),可以通过多种方式定义顶点。 Vertices 示例项目中的顶点格式如以下代码片段所示:
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // The transformed position for the vertex.
DWORD color; // The vertex color.
};
上面的结构指定了自定义顶点类型的格式。 下一步是定义描述顶点缓冲区中顶点内容的 FVF。 以下代码片段定义了一个与上面创建的自定义顶点类型相对应的 FVF。
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
D3DFVF 描述了正在使用的自定义顶点的类型。 上面的示例代码使用 D3DFVF_XYZRHW 和 D3DFVF_DIFFUSE 标志,它们告诉顶点缓冲区自定义顶点类型有一个变换点,后跟一个颜色分量。
既然已经指定了自定义向量格式和 FVF,下一步就是用顶点填充顶点缓冲区,如第 2 步 - 设置顶点缓冲区中所述。
笔记 |
---|
Vertices 示例项目中的顶点被转换。 换句话说,它们已经在 2D 窗口坐标中。 这意味着点 (0,0) 在左上角,正 x 轴在右,正 y 轴在下。 这些顶点也被照亮,这意味着它们没有使用 Direct3D 光照,而是提供自己的颜色。 |
第 2 步 - 设置顶点缓冲区
现在已经定义了自定义顶点格式,是时候初始化顶点了。 Vertices 示例项目通过在创建所需的 Direct3D 对象后调用应用程序定义的函数 InitVB 来执行此操作。 以下代码片段初始化三个自定义顶点的值。
CUSTOMVERTEX vertices[] =
{
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
};
前面的代码片段用三角形的点填充三个顶点,并指定每个顶点将发出哪种颜色。 第一个点位于 (150, 50) 并发出红色 (0xffff0000)。 第二个点位于 (250, 250) 并发出绿色 (0xff00ff00)。 第三个点位于 (50, 250) 并发出蓝绿色 (0xff00ffff)。 这些点中的每一个都具有 0.5 的深度值和 1.0 的 RHW。
下一步是调用 IDirect3DDevice9::CreateVertexBuffer 来创建一个顶点缓冲区,如以下代码片段所示。
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0 /*Usage*/, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
return E_FAIL;
IDirect3DDevice9::CreateVertexBuffer 的前两个参数告诉 Direct3D 新顶点缓冲区所需的大小和用途。 接下来的两个参数指定新缓冲区的向量格式和内存位置。 这里的向量格式是D3DFVF_CUSTOMVERTEX,也就是前面示例代码指定的灵活顶点格式(FVF)。 D3DPOOL_DEFAULT 标志告诉 Direct3D 在最适合此缓冲区的内存分配中创建顶点缓冲区。 最后一个参数是要创建的顶点缓冲区的地址。
创建顶点缓冲区后,它会填充来自自定义顶点的数据,如以下代码片段所示。
VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices, sizeof(vertices) );
g_pVB->Unlock();
首先通过调用 IDirect3DVertexBuffer9::Lock 来锁定顶点缓冲区。 第一个参数是要锁定的顶点数据的偏移量,以字节为单位。 第二个参数是要锁定的顶点数据的大小,以字节为单位。 第三个参数是一个 BYTE 指针的地址,用指向顶点数据的指针填充。 第四个参数告诉顶点缓冲区如何锁定数据。
然后使用 memcpy 将顶点复制到顶点缓冲区中。 在顶点进入顶点缓冲区后,调用 IDirect3DVertexBuffer9::Unlock 来解锁顶点缓冲区。 需要这种锁定和解锁机制,因为顶点缓冲区可能位于设备内存中。
现在顶点缓冲区已被顶点填充,是时候渲染显示了,如第 3 步 - 渲染显示中所述。
第 3 步 - 渲染显示
现在顶点缓冲区已经填充了顶点,是时候渲染显示了。 渲染显示首先将后台缓冲区清除为蓝色,然后调用 BeginScene。
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0L );
g_pd3dDevice->BeginScene();
从顶点缓冲区渲染顶点数据需要几个步骤。 首先需要设置流源; 在这种情况下,使用流 0。通过调用 IDirect3DDevice9::SetStreamSource 指定流的源。
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
第一个参数是流号,第二个参数是指向顶点缓冲区的指针。 第三个参数是从流开始到顶点数据开始的偏移量,在这个例子中是0。 最后一个参数是顶点声明中每个元素的字节数。
下一步是调用 IDirect3DDevice9::SetFVF 来识别固定函数顶点着色器。 完整的自定义顶点着色器是一个高级主题,但在这种情况下,顶点着色器只是灵活的顶点格式 (FVF) 代码。 以下代码片段设置 FVF 代码。
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
SetFVF 的唯一参数是定义顶点数据布局的固定顶点函数代码。
下一步是使用 IDirect3DDevice9::DrawPrimitive 渲染顶点缓冲区中的顶点,如以下代码片段所示。
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
DrawPrimitive 接受的第一个参数是一个标志,它告诉 Direct3D 要绘制哪种类型的图元。 此示例使用标志 D3DPT_TRIANGLELIST 来指定三角形列表。 第二个参数是要加载的第一个顶点的索引。 第三个参数告诉要绘制的图元数量。 由于此示例仅绘制一个三角形,因此该值设置为 1。
有关不同类型基元的更多信息,请参阅基元。
最后一步是结束场景,然后将后台缓冲区呈现给前台缓冲区。 这显示在以下代码片段中。
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
后缓冲区呈现给前缓冲区后,客户端窗口显示一个带有三个不同颜色点的三角形。
本教程向您展示了如何使用顶点来渲染几何形状。 教程 3:使用矩阵介绍了矩阵的概念以及如何使用它们。
运行效果: