版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DY_1024/article/details/84285476
首先里面还是有两个基本的文件:d3dUtility.h以及d3dUtility.cpp
里面的主要内容就是实现Direct3D的初始化,以及模板函数的的实现,和消息循环函数的声明,回调函数的声明。
具体的解释在博客:在屏幕绘制一个三角形以及Direct3D初始化例程中有详细的解释,这里就不在过多的重复。
我们主要来看主函数文件Cube.cpp里面是怎么实现,我们在代码中详细的讲解,下面是cube.cpp内容:
//包含头文件
#include "d3dUtility.h"
//定义一个设备类型的指针,准备指向设备
IDirect3DDevice9* Device = 0;
//定义两个数据,用来规定窗口的大小
const int Width = 640;
const int Height = 480;
//定义两个指针,一个准备指向顶点缓存(VertexBuffer),一个准备指向索引缓存(IndexBuffer)
IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9* IB = 0;
//定义一个顶点,里面有x,y,z坐标
struct Vertex
{
Vertex() {}
Vertex(float x, float y, float z)
{
_x = x; _y = y; _z = z;
}
float _x, _y, _z;
static const DWORD FVF;
};
//顶点的灵活顶点格式的定义
const DWORD Vertex::FVF = D3DFVF_XYZ;
//资源的分配
bool Setup()
{
//将我们刚才创建的顶点缓存VP进行实例化
Device->CreateVertexBuffer(
8 * sizeof(Vertex), //开辟可以存放8个顶点的缓存用来给VP指
D3DUSAGE_WRITEONLY, //顶点缓存的使用格式,是几个枚举类型,这个枚举类型表示创建的顶点缓存只能写
Vertex::FVF, //将顶点的灵活顶点格式传进来
D3DPOOL_MANAGED, //内存池得类型
&VB, //定义的顶点缓存的指针
0); //不使用,文档里面说是给Window Vista使用
//将我们刚才创建的索引缓存进行IP实例化
Device->CreateIndexBuffer(
36 * sizeof(WORD), //开辟可以存放36个索引的空间给IP指
D3DUSAGE_WRITEONLY, //索引缓存的属性,同上面的顶点缓存的对应参数
D3DFMT_INDEX16, //索引缓存的位数,32位和16位,32位有些硬件不支持
D3DPOOL_MANAGED, //内存池的类型
&IB, //定义的指向索引缓存的指针
0); //不使用,文档里面说是给Window Vista使用
//用顶点的结构定义一个指针,用来
Vertex* vertices;
//对方问的顶点进行上锁
VB->Lock(0, 0, (void**)&vertices, 0);
//对顶点进行赋值,正方形有8个点
vertices[0] = Vertex(-1.0f, -1.0f, -1.0f);
vertices[1] = Vertex(-1.0f, 1.0f, -1.0f);
vertices[2] = Vertex(1.0f, 1.0f, -1.0f);
vertices[3] = Vertex(1.0f, -1.0f, -1.0f);
vertices[4] = Vertex(-1.0f, -1.0f, 1.0f);
vertices[5] = Vertex(-1.0f, 1.0f, 1.0f);
vertices[6] = Vertex(1.0f, 1.0f, 1.0f);
vertices[7] = Vertex(1.0f, -1.0f, 1.0f);
//解锁
VB->Unlock();
// 定义多维数据集的三角形
WORD* indices = 0;
IB->Lock(0, 0, (void**)&indices, 0);
//里面存放的是vertices数组里面的索引,
/* 前面要绘制两个三角形,
第一个三角形,索引缓存0,1,2里面分别存放的是顶点vertices[0],vertices[1],vertices[2]
第二个三角形,索引缓存3,4,5里面分别存放的是顶点vertices[0],vertices[2],vertices[3]
索引缓存里面存放的是顶点缓存里面顶点的索引
后面同理
*/
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 2; indices[5] = 3;
// 后面
indices[6] = 4; indices[7] = 6; indices[8] = 5;
indices[9] = 4; indices[10] = 7; indices[11] = 6;
// 左面
indices[12] = 4; indices[13] = 5; indices[14] = 1;
indices[15] = 4; indices[16] = 1; indices[17] = 0;
// 右面
indices[18] = 3; indices[19] = 2; indices[20] = 6;
indices[21] = 3; indices[22] = 6; indices[23] = 7;
// 上面
indices[24] = 1; indices[25] = 5; indices[26] = 6;
indices[27] = 1; indices[28] = 6; indices[29] = 2;
// 下面
indices[30] = 4; indices[31] = 0; indices[32] = 3;
indices[33] = 4; indices[34] = 3; indices[35] = 7;
IB->Unlock();
//摄影机在世界坐标中的位置
D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
//被观察的点在世界坐标的位置
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
//世界坐标系中向上方向的向量
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX V;
//通过这个接口获取世界矩阵
D3DXMatrixLookAtLH(&V, &position, &target, &up);
//设施世界矩阵
Device->SetTransform(D3DTS_VIEW, &V);
//用于接收投影矩阵的矩阵
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f, // 视域体的视域角:90度
(float)Width / (float)Height,//纵横比:为了减少正方形矩阵映射到矩形屏幕之后的畸变
1.0f, //到近平面的距离
1000.0f); //到原平面的距离
//设施投影矩阵
Device->SetTransform(D3DTS_PROJECTION, &proj);
//设置绘制状态
Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
return true;
}
void Cleanup()
{
d3d::Release<IDirect3DVertexBuffer9*>(VB);
d3d::Release<IDirect3DIndexBuffer9*>(IB);
}
bool Display(float timeDelta)
{
if (Device)
{
//定义两个矩阵
D3DXMATRIX Rx, Ry;
// 得到一个矩阵Rx:乘这个矩阵就相当于:在X轴上旋转45度
D3DXMatrixRotationX(&Rx, 3.14f / 4.0f);
// 每一帧增加y的旋转角度
static float y = 0.0f;
//得到一个矩阵Ry:乘以这个矩阵就相当于在Y轴旋转y度,y是一直在变化的
D3DXMatrixRotationY(&Ry, y);
y += timeDelta;
//如果角度大于360度,也就是转了一圈,就将y轴的旋转角度重置为0
if (y >= 6.28f)
y = 0.0f;
// 结合矩阵Rx以及Ry,
D3DXMATRIX p = Rx * Ry;
//设置世界矩阵
Device->SetTransform(D3DTS_WORLD, &p);
//清屏
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
Device->BeginScene();
//将顶点缓存和数据流链接
Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
//设置索引缓存
Device->SetIndices(IB);
//设置灵活顶点格式
Device->SetFVF(Vertex::FVF);
//使用接口画出来
Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
Device->EndScene();
//在设备拥有的后台缓冲区中显示下一个内容
Device->Present(0, 0, 0, 0);
}
return true;
}
//回调函数
//当窗口收到消息的时候应该做出什么动作
//这个函数功能就是:按键“ESC”,窗口退出
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
::DestroyWindow(hwnd);
break;
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
//
int WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
//Direct3d初始化
if (!d3d::InitD3D(hinstance,
Width, Height, true, D3DDEVTYPE_HAL, &Device))
{
::MessageBox(0, "InitD3D() - FAILED", 0, 0);
return 0;
}
//分配资源
if (!Setup())
{
::MessageBox(0, "Setup() - FAILED", 0, 0);
return 0;
}
//调用Display画出来
d3d::EnterMsgLoop(Display);
Cleanup();
Device->Release();
return 0;
}