创建D3D窗口(二)

2018-11-27  本文已影响0人  六六大魔头

D3D创建(二)

要把普通窗口改造成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;
}
上一篇下一篇

猜你喜欢

热点阅读