1. 颜色表示
在 Direct3D 中。颜色用 RGB 三元组表示。RGB 数据可用两种不同的结构来保存。第一种是 D3DCOLOR ,它实际上与 DWORD 类型完全相同(由 typedef 定义),共有 32 位。 D3DCOLOR 类型中各位被分成 8 位项(section),每项存储了一种颜色分量的亮度值(Alpha,,R,G,B)。每项均占一个字节,所以每个分量的亮度值范围都在[0,255]区间内,接近 0 值表示最小值,接近 255 的值表示高度值。
Direct3D 提供了宏 帮助我们完成将颜色分量值,安插到 D3DCOLOR 类型的合适位置上。也可以使用 D3DCOLOR_XRGB 宏来代替 D3DCOLOR_ARGB,两者很相似, 不接受 Alpha 参数(将 Alpha 分量设为 0xff(255) )。
在 Direct3D 中,存储颜色的数据的另一种结构是 。在该结构中,我们使用单精度浮点数来度量每个颜色分量的亮度值。亮度范围为(0~1)。
我们可以利用 代替 D3DCOLORVALUE,前者不但包含了与后者相同的数据成员,而且还提供了一组有用的构造函数和重载运算符,为颜色的运算提供了便利。
2. 顶点颜色
图元的颜色由构成该图元的顶点的颜色所决定。所以,我们必须为顶点数据结构添加一个表示颜色的数据成员。
3. 着色
在光栅化过程中,需要对多边形进行着色(shading)。着色规定了如何利用顶点的颜色来计算构成图元的像素的颜色。目前,我们使用两种着色模式(shading mode):
(1) 平面着色 (flat shading)。每个图元的每个像素都被一致地赋予该图元的第一个顶点所指定的颜色。即使用平面着色时,如果第一个顶点是红色的,那么其他顶点的颜色值将被忽略。平面着色容易使物体呈现出“块状”,这是因为各颜色之间没有平滑地过度。
(2) Gouraud 着色 (Gouraud Shading)。图元中个像素的颜色值由各顶点的颜色线性插值得到。各个颜色之间的平滑的过度,因此Gouraud 着色也称平滑着色(smooth shading)。
4. 例程(DrawColorTriangle)
在 的框架上添加代码。
(1) 新建头文件 GlobalColorConstant.h ,添加一些颜色全局常量:
#ifndef __GLOBALCOLOR_CONSTANT_H__ #define __GLOBALCOLOR_CONSTANT_H__ const D3DXCOLOR WHITE ( D3DCOLOR_XRGB(255, 255, 255) ); const D3DXCOLOR BLACK ( D3DCOLOR_XRGB( 0, 0, 0) ); const D3DXCOLOR RED ( D3DCOLOR_XRGB(255, 0, 0) ); const D3DXCOLOR GREEN ( D3DCOLOR_XRGB( 0, 255, 0) ); const D3DXCOLOR BLUE ( D3DCOLOR_XRGB( 0, 0, 255) ); const D3DXCOLOR YELLW ( D3DCOLOR_XRGB(255, 255, 0) ); const D3DXCOLOR CYAN ( D3DCOLOR_XRGB( 0, 255, 255) ); const D3DXCOLOR MAGENTA( D3DCOLOR_XRGB(255, 0, 255) ); #endif /* __GLOBALCOLOR_CONSTANT_H__ */
(2) 新建头文件 ColorVertex.h 添加有色顶点的结构体定义:
#ifndef __COLORVERTEX_H__ #define __COLORVERTEX_H__ struct ColorVertex { public: ColorVertex(float x, float y, float z, D3DCOLOR color) { m_x = x; m_y = y; m_z = z; m_color = color; } public: static const DWORD FVF; private: float m_x; float m_y; float m_z; D3DCOLOR m_color; }; const DWORD ColorVertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; #endif /* __COLORVERTEX_H__ */
(3)在 Direct3DFrame 类中添加代码:
D3DXMATRIX m_worldMatrix; // 存储所要绘制三角形的世界变换矩阵 IDirect3DVertexBuffer9* m_triangle; // 保存三角形数据的定点缓存
(4) Setup 方法创建了一个顶点缓存,并用所要绘制的三角形中带有颜色信息的顶点对该缓存进行填充。该三角形第 1 个顶点的颜色为红色,第 2 个顶点的颜色为绿色,第 3 个顶点为蓝色。在本例的最后,将光照禁用。
bool Direct3DFrame::Setup() { // Create the vertex buffer. m_device->CreateVertexBuffer( 3*sizeof(ColorVertex), D3DUSAGE_WRITEONLY, ColorVertex::FVF, D3DPOOL_MANAGED, &m_triangle, 0); // Fill the buffer with the triangle data. ColorVertex* v; m_triangle->Lock(0, 0, (void**)&v, 0); v[0] = ColorVertex(-1.0f, 0.0f, 2.0f, RED); v[1] = ColorVertex( 0.0f, 1.0f, 2.0f, GREEN); v[2] = ColorVertex( 1.0f, 0.0f, 2.0f, BLUE); m_triangle->Unlock(); // Set the projection matrix. D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.5f, (float)m_width / (float)m_height, 1.0f, 1000.0f); m_device->SetTransform(D3DTS_PROJECTION, &proj); // Turn off lighting. m_device->SetRenderState(D3DRS_LIGHTING, false); return true; }
(5) Display 函数在两个不同的位置以两种不同的着色模式分别绘制 Triangle。每个三角形位置由世界变换矩阵 World 来控制。
bool Direct3DFrame::Display(float timeDelta) { if (m_device) { m_device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0); m_device->BeginScene(); m_device->SetFVF(ColorVertex::FVF); m_device->SetStreamSource(0, m_triangle, 0, sizeof(ColorVertex)); // draw the triangle to the left with flat shading D3DXMatrixTranslation(&m_worldMatrix, -1.25f, 0.0f, 0.0f); m_device->SetTransform(D3DTS_WORLD, &m_worldMatrix); m_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT); m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); // draw the triangle to the right with gouraud shading D3DXMatrixTranslation(&m_worldMatrix, 1.25f, 0.0f, 0.0f); m_device->SetTransform(D3DTS_WORLD, &m_worldMatrix); m_device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); m_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); m_device->EndScene(); m_device->Present(0, 0, 0, 0); } return true; }
(6) 在 Cleanup 中释放资源
void Direct3DFrame::Cleanup() { m_device->Release(); m_triangle->Release(); }
运行后截图:
/*******************************************************/
** 本文由 原创,转载请注明博客链接,谢谢!
** 小弟初学 Direct3D,文章中如果存在错误,烦请指证,不胜感激!
** 参考书籍:《DirectX 9.0 3D 游戏开发编程基础》
** 时间:2011.11.21
/*******************************************************/