问题2-D3D Color

这次是学习DX中对颜色的处理。使用ColorVertex这种结构体保存带有染色的顶点,然后对物体进行渲染。
问题描述:
在窗口中显示两个立方体,其中一个使用D3DSHADE_GOURAUD渲染模式,一个使用D3DSHADE_FLAT渲染模式;并且使两个立方体各自绕X,Y,Z轴自转的同时,两个立方体同时绕Y轴公转。

为了要使用带颜色的定点,我们可以先在头文件里定义颜色常量,
const D3DXCOLOR WHITE( D3DCOLOR_XRGB(255, 255, 255) );
const D3DXCOLOR BLACK( D3DCOLOR_XRGB( 0, 0, 0) );
可以像这样定义自己想要的颜色。然后定义带颜色的顶点:
struct ColorVertex
{
ColorVertex(){}
ColorVertex(float x,float y,float z,D3DCOLOR c)
{
_x = x;
_y = y;
_z = z;
_color = c;
}
float _x,_y,_z;
D3DCOLOR _color;
static const DWORD FVF;
};
const DWORD ColorVertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
这里的结构和不带颜色的定点结构是一样的,只不过就多了一个color参数。这种定点的结构也可以当成公式一样记忆下来。要画出一个立方体,我们这里要使用设备的CreateVertexBuffer和CreateIndexBuffer,这里要注意一点,一个立方体有8个顶点,所以我们的顶点数是8,但是index的话,就有36个了,立方体是6个面,一个面是6个index,因为在画每一个面的时候,是用2个三角形组合而成的,每个三角形都要用3个index,在一个四边形中画条对角线,就可以知道了,2个三角形,虽然2个顶点是一样的,但是还是要算在总数里面,所以6×6就是36个index。
Device->CreateVertexBuffer(
8 * sizeof(ColorVertex),
D3DUSAGE_WRITEONLY,
ColorVertex::FVF,
D3DPOOL_MANAGED,
&VB,
0);
ColorVertex* v;
VB->Lock(0,0,(void**)&v,0);
v[0] = ColorVertex(-1.0f, -1.0f, -1.0f, d3d::BLUE);
v[1] = ColorVertex(-1.0f, 1.0f, -1.0f, d3d::PURPLE);
v[2] = ColorVertex( 1.0f, 1.0f, -1.0f, d3d::RED);
v[3] = ColorVertex( 1.0f, -1.0f, -1.0f, d3d::MAGENTA);
v[4] = ColorVertex(-1.0f, -1.0f, 1.0f, d3d::CYAN);
v[5] = ColorVertex(-1.0f, 1.0f, 1.0f, d3d::GREEN);
v[6] = ColorVertex( 1.0f, 1.0f, 1.0f, d3d::YELLOW);
v[7] = ColorVertex( 1.0f, -1.0f, 1.0f, d3d::WHITE);
VB->Unlock();
Device->CreateIndexBuffer(
36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&IB,
0);
WORD* indices = 0;
IB->Lock(0, 0, (void**)&indices, 0);
// front side
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
// back side
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
// left side
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
// right side
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
// top
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
// bottom
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
IB->Unlock();
上面的代码就是分别设置顶点缓冲和index缓冲,VB,IB分别是
IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9* IB = 0;
在设置顶点和index前一定要调用Lock方法,在设置完成后也一定要Unlock。还有一点要注意的地方,就是在设置index的时候,顺序是有讲究的,也就是说所有三角形(也就是indices[0] = 0; indices[1] = 1; indices[2] = 2;这里决定的三角形)画线的方向必须一致。也就是说所有三角形都是顺时针方向或都是反时针方向。
立方体画好了后,就要设置它的旋转了。上篇文章中已经讲了绕轴自转的方法。这里主要说一下公转的方法。其实公转和简单,我之前也搞不懂,想了很久,在网上问了很多朋友,还是没有解决,最后在一次不经意的测试中发现了公转的秘密。呵呵~
前面说过了,让物体在替他坐标点自转,需要用平移向量点乘旋转向量,而且要注意方向,也就是平移向量要放在前面,如果这2个顺序换一下,把旋转向量放在前面,会出现什么结果呢??答案正是我们想要的公转!所以这里我们只需要交换点乘前后参数的位子就可以了。比如:
D3DXMatrixMultiply(&Position1,&Position1, &Ry);
这样就可以让物体绕Y轴公转,公转后再让物体自转就可以到达我们的要求了。
最后在窗口中显示物体(当然设定投影和摄像机这里省略了):
Device->SetStreamSource(0, VB, 0, sizeof(ColorVertex));
Device->SetIndices(IB);
Device->SetFVF(ColorVertex::FVF);
Device->SetTransform(D3DTS_WORLD,&Position1);
Device->SetRenderState(D3DRS_SHADEMODE,D3DSHADE_GOURAUD);
Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
要显示另一个立方体,再使用后面三句就可以了,不过要改变显示的坐标哦。程序完成后,就可以看到2种不同渲染方法的差别了。
*原创文章,转载请注明出处*


