D3D创建(二)
- 上篇文章我们实现了普通的Windows窗口,这次我们就要在之前代码的基础上将其改写成d3d窗口。
首先要做的是包含头文件d3d9.h,然后设定库目录,包含目录,并链接LIB文件。删除以前写的包含windows.h头文件的代码,因为在d3d9.h中已经帮我们包含了windows.h头文件,我们在包含的话就会产生重复包含错误。
要把普通窗口改造成d3d窗口,我们实现4个函数——初始化d3d、初始化物体、绘制、释放内存。
首先我们定义出设备指针,设备对象指针。
#include"d3d9.h"
#pragma comment(lib,"d3d9.lib")
LPDIRECT3D9 g_D3D = NULL;
//D3D指针
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;
//D3D设备对象指针
实现第一个函数,用于初始化D3D设备对象
bool initialized3d(HWND hWnd,bool FullScreen)
函数返回值为布尔型,用于接收处理结果
参数HWND:要初始化的句柄
参数bool:要初始化的是否是全屏窗口
bool InitializeD3D(HWND hWnd,bool FullScreen)
{
D3DDISPLAYMODE displaymode;
//D3D显示模式结构体,用于获取显卡的能力信息
g_D3D= Direct3DCreate9(D3D_SDK_VERSION);
//根据D3D版本创建D3D对象指针
if(g_D3D!= NULL) return false;
if (g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displaymode)) return false;
//D3DADPTER_DEFUALT 指定获取的设备 这里指定默认显卡
//displaymode 所有获取信息填充进的结构体
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
if (FullScreen)
{
d3dpp.Windowed = false;
d3dpp.BackBufferWidth = WindowWidth;
dedpp.BackBufferHeight = WindowHeight;
}
else
{
d3dpp.Windowed = TRUE;
}
//这里分全屏和窗口两个模式,在全屏模式下后台缓冲宽度和高度都不用指定
//窗口模式下需要指定缓冲区大小 这里做个判断 如果窗口宽度高度都等于窗口宽度高度
d3dpp.BackBufferFormat = displaymode.Format;
//指定后台缓冲格式 之前获取的结构体内就有后台缓冲格式
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
//指定d3d后台交换模式 这里用最快的剪裁模式 类似的模式还有拷贝翻转等 根据自己需要选择
if (FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,&d3dpp,&g_device);
))
这里的D3DPARATERS结构体不需要我们填充所有值,如果是窗口,Windowed赋值FALSE,填入BackBufferWidth,BackBufferHeight,BackBufferFormat,SwapEffect。如果是全屏我们Windowed赋值TRUE,并填充BackBufferFormat,SwapEffect。参数功能如下
BackBufferWidth,BackBufferHeight后台缓存大小,在全屏下无效,窗口模式下我直接赋值为窗口大小。
BackBufferFormat 后台缓存格式,这里使用获取到的格式。
SwapEffect 后备缓存区交换方式,我们使用最快的D3DSWAPEFFECT_DISCARD
接下来改造一下我们的消息循环
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
RenderScene();
}
//此处修改效果为只要没有收到推出的消息便一直循环 获取到消息就立即处理消息,若没有消息就渲染D3D 选择在空闲时候渲染窗口
}
接下来我们实现渲染函数。
Render()
{
g_D3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRBG(0,0,0),1.0f,0);
//使用D3D设备对象内的Clear函数清空当前显示信息
g_D3DDevice->BeginScene();
//开始渲染
//这里写入渲染代码
g_D3DDevice->EndScene();
//结束渲染
g_D3DDevice->Present(NULL,NULL,NULL,NULL);
//显示渲染的帧
}
别忘记,用完所有指针后记得释放所有资源,大量的内存不释放将会导致内存泄漏。这里我创建Shutdown函数来释放已用资源
void Shutdown()
{
if (g_D3DDevice != NULL) g_D3DDevice->Release();
if (g_D3D != NULL) g_D3D->Release();
//如果指针存在则释放指针资源
g_D3DDevice = NULL;
g_D3D = NULL;
释放后指针赋空,杜绝空指针
}
完整代码
#include "d3d9.h"
#define ClassName "UGPDX"
#define WindowName "Demo_Window"
#define MenuName NULL
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#pragma comment(lib,"d3d9.lib")
bool InitializeD3D(HWND hWnd, bool fullscreen);
void RenderScene();
void Shutdown();
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice = NULL;
LRESULT WINAPI WndPro(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndPro,NULL,NULL,hInstance,NULL,NULL,NULL
,MenuName,ClassName };
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(NULL, ClassName, WindowName, WS_OVERLAPPEDWINDOW, 100, 100, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
if (InitializeD3D(hWnd, false))
{
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
RenderScene();
}
}
Shutdown();
UnregisterClass(ClassName, hInstance);
return 0;
}
return 0;
}
bool InitializeD3D(HWND hWnd, bool fullscreen)
{
D3DDISPLAYMODE displaymode;
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!g_D3D) return false;
if (g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displaymode)) return false;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
if (fullscreen)
{
d3dpp.Windowed = false;
d3dpp.BackBufferWidth = WINDOW_WIDTH;
d3dpp.BackBufferHeight = WINDOW_HEIGHT;
}
else
{
d3dpp.Windowed = TRUE;
}
d3dpp.BackBufferFormat = displaymode.Format;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
if (FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_D3DDevice)))
{
return false;
}
return true;
}
void RenderScene()
{
g_D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
g_D3DDevice->BeginScene();
//开始渲染
g_D3DDevice->EndScene();
//结束场景渲染
g_D3DDevice->Present(NULL, NULL, NULL, NULL);
//显示渲染
}
void Shutdown()
{
if (g_D3DDevice != NULL) g_D3DDevice->Release();
if (g_D3D != NULL) g_D3D->Release();
g_D3DDevice = NULL;
g_D3D = NULL;
}
网友评论