1. 使用顶点缓存绘制静止图形
1.0 模型表示
struct Vertex
{
float _x, _y, _z, _rhw;
DWORD _color;
Vertex(float x, float y, float z, float rhw, DWORD color):
_x(x), _y(y), _z(z), _rhw(rhw), _color(color){}
static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
D3DFVF_XYZRHW和D3DFVF_XYZ的区别
device->SetRenderState(D3DRS_LIGHTING, false);
由于不需要进行各类坐标变换,因此只要直接设置顶点缓存即可
IDirect3DVertexBuffer *pVB = NULL;
Device->CreateVertexBuffer(3 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::FVF,
D3DPOOL_MANAGED,
&pVB,
NULL);
//然后填充顶点缓存
Vertex *vertices;
pVB->Lock(0, 0, (void**)&vertices, 0);
//第三个参数传入了void**,意味着可能更改指针自身的值,而数组名指向的地址是不可以被更改的,因而上一行必须定义为指针,定义为数组会出错,下面开始填充
vertices[0] = Vertex(400.0f, 150.0f, 0.0f, 1.0f, 0xffff0000);
vertices[1] = Vertex(600.0f, 450.0f, 0.0f, 1.0f, 0xff00ff00);
vertices[2] = Vertex(200.0f, 450.0f, 0.0f, 1.0f, 0xff0000ff);
pVB->Unlock();
参数中D3DUSAGE的取值
至此完成了模型的定义,接下来就可以进行绘制了
缓存区域
显卡缓存层次结构
1.1 绘制
我们编制的D3D框架中,绘制图象的工作在Render函数中完成,Render的基本结构如下,我们的绘制代码就将填充在BeginScene和EndScene之间
bool Render(float DeltaTime)
{
Device->Clear(...);
if(Device->BeginScene())
{
//TODO: Drawing codes
Device->EndScene();
}
Device->Present(...);
return true;
}
绘制工作分为四步
Device->SetStreamSource(...);
Device->SetFVF(...);
Device->SetIndices(...);
Device->DrawPrimitive(...);
在本例中代码即为
bool Render(float DelteTime)
{
//Set BackBuffer to white
pD3DDEV->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
//Set Wireframe
//pD3DDEV->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
//Render
if( SUCCEEDED(pD3DDEV->BeginScene()) )
{
//All actual render operations should be enclosed by BeginScene and EndScene
//Step 1. Set Source of data stream
pD3DDEV->SetStreamSource(0, pVB, 0, sizeof(COLORED_VERTEX));
//Step 2. Set Vertex Format, aka. FVF
pD3DDEV->SetFVF(D3DFVF_COLOREDVERTEX);
//Step 3(Optional). Set Index Buffer, only needed when using index buffer
//Step 4. Draw
pD3DDEV->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
//Finish Drawing
pD3DDEV->EndScene();
}
//Present BackBuffer
pD3DDEV->Present(NULL, NULL, NULL, NULL);
return true;
}
2. 使用索引缓存绘制动态图像
效果图
要说明的是,这儿直接使用顶点缓存也是可以的,但是正如图中所示,一个立方体有8个顶点,但描述这个立方体需要36个顶点,每个顶点被使用了四次,如果这儿使用索引缓存,则顶点缓存只需要储存8个顶点即可
Device->CreateIndexBuffer(3 * sizeof(DWORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&pIB,
0);
WORD *indices = 0;
pIB->Lock(0, 0, (void**)&indices, 0);
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
pIB->Unlock();
由于我们要建立动态图像,所以D3DFVF_XYZRHW格式不再适合,需要使用D3DFVF_XYZ格式并设置各类变换矩阵
D3DXMATRIX cam;
D3DXVECTOR3 EyeAt(0.0f, 0.0f, -3.0f);
D3DXVECTOR3 LookAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtLH(&cam, &EyeAt, &LookAt, &up);
pD3DDEV->SetTransform(D3DTS_VIEW, &cam);
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj,
D3DX_PI * 0.5f, //FoV, Field of View
800.0f/ 600.0f, //Aspect Ratio
1.0f, //Z-near
100.0f); //Z-far
pD3DDEV->SetTransform(D3DTS_PROJECTION, &proj);
D3DXMATRIX ry;
static float y = 0.0f;
D3DXMatrixRotationY(&ry, y);
y += DeltaTime;
if( y >= 6.28f )
y = 0.0f;
pD3DDEV->SetTransform(D3DTS_WORLD, &ry);
绘图模式:由于三角形旋转过程中会将背面转向摄像机,因此要取消背面消隐,否则背面旋转到面向摄像机的时候不会显示,此外,前面也提过,使用D3DFVF_XYZ时要关闭光照
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
Device->SetRenderState(D3DRS_LIGHTING, false);
由于图形旋转过程中,有了Z方向的变化,因此在绘图前清除缓冲区时要一并清除Z缓存
pD3DDEV->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
Written with StackEdit.