版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DY_1024/article/details/84258909
首先头文件d3dUtility.h里面:
Init3D函数:里面实现了Direct3D初始化的整个过程:包括获取接口Direct3D9的指针,检验设备的顶点运算,填充设备属性结构体的内容,创建IDirect3DDevice9的接口等。
EnterMsgLoop函数:该函数接受了一个显示函数的函数指针,然后将应用程序的消息循环进行封装,穿进去的显示函数就是进行绘制的函数,然后EnterMsgLoop函数需要知道什么时候去调用这个显示函数进行显示。
Release模板和Delete模板:资源销毁的时候调用。
头文件可以在这篇博客中找到,直接复制就能用。
还有就是d3dUtility.cpp文件,里面具体实现了刚才我们在d3dUtility.h文件中声明的两个函数。
同样也可以在这篇博客中找到,直接复制拷贝就可以用。
然后在源文件中我们还需要我们的主文件,也就是绘制Triangle的文件:triangle.cpp。我们在代码中以注释的方式进行讲解,会比较明了一点。
//包含我们刚才创建的d3dUtility.h头文件
#include "d3dUtility.h"
//定义一个用来指向设备的指针
IDirect3DDevice9* Device = 0;
//设置好我们窗口的宽和高
const int Width = 640;
const int Height = 480;
//定义一个用来顶点缓存的指针,用来指向我们的三角形顶点的数据
IDirect3DVertexBuffer9* Triangle = 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()
{
//使用接口:CreateVertexBuffer创建顶点缓存
Device->CreateVertexBuffer(
3 * sizeof(Vertex), // 因为我们只去画一个三角形,所以只有三个顶点,这里就给他开辟三个顶点的空间
D3DUSAGE_WRITEONLY, // 这个标记代表现在创建的缓存是:只能写的静态缓存
Vertex::FVF, // 灵活顶点格式
D3DPOOL_MANAGED, // 内存池的类型
&Triangle, // 指向顶点缓存的指针的指针
0); // CreatVertexBuffer的最后一个参数,不使用,设置为0,具体参见链接
//使用顶点结构体定义的顶点指针
Vertex* vertices;
//使用之前将要访问的顶点缓存进行上锁
Triangle->Lock(0, 0, (void**)&vertices, 0);
//对顶点缓存进行赋值操作
vertices[0] = Vertex(-1.0f, 0.0f, 2.0f);
vertices[1] = Vertex(0.0f, 1.0f, 2.0f);
vertices[2] = Vertex(1.0f, 0.0f, 2.0f);
//对顶点缓存使用完成之后进行解锁
Triangle->Unlock();
/*正常来说,点设置好之后,经过的变换是:局部坐标系->世界坐标系->观察坐标系->背面消隐
->光照->裁剪->投影变换->视口变换->光栅化
但是现在只有一个2D的三角形,窗口中(也可以理解成世界坐标和局部坐标是同一个坐标)只有这么一个图形,所以直接进行投影变换
*/
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj, // 要得到的投影矩阵
D3DX_PI * 0.5f, // 视域体中的视角
(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模板,进行资源的释放
d3d::Release<IDirect3DVertexBuffer9*>(Triangle);
}
//显示韩式
bool Display(float timeDelta)
{
//如果Device存在或者不为空,则进入判断
if (Device)
{
//使用此方法进行清除表面
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
//绘制必须是在BeginScene和EndScene之间
Device->BeginScene();
//将需要绘制的顶点缓存和数据流进行链接
Device->SetStreamSource(0, Triangle, 0, sizeof(Vertex));
//设置灵活顶点格式
Device->SetFVF(Vertex::FVF);
// 绘制三角形
Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
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;
//当按键 = ESC 的时候摧毁窗口,并发送一条WM_DESTROY消息
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
::DestroyWindow(hwnd);
break;
}
//没有消息的时候应该调用怎么做
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
//
// WinMain
//
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,就是调用:DrawPrimitive进行绘制的过程
d3d::EnterMsgLoop(Display);
Cleanup();
Device->Release();
return 0;
}
triangle.cpp里面提到的链接是这两篇博客,里面对函数的使用以及一些相关的概念都有详细的解释: