Directx11学习笔记 封装一个简单的Dx11DemoBase

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Directx11学习笔记 封装一个简单的Dx11DemoBase相关的知识,希望对你有一定的参考价值。

根据前面两个笔记的内容,我们来封装一个简单的基类,方便以后的使用。 代码和前面类似,没有什么新的内容,直接看代码吧(由于代码上次都注释了,这次代码就没怎么写注释o(╯□╰)o) Dx11DemoBase.h

Dx11DemoBase.h

#pragma once
#include <d3d11.h>
#include <D3DX11.h>
#include <DxErr.h>

class Dx11DemoBase
{
public:
    Dx11DemoBase();
    virtual ~Dx11DemoBase();

    bool Initialize(HINSTANCE hInstance, HWND hWnd);
    void ShutDown();//释放内存

    virtual bool LoadContent();//载入具体的Demo自己的内容,如纹理,几何体,着色器
    virtual void UnLoadContent();//释放具体Demo中的内容

    virtual void Update(float dt) = 0;
    virtual void Render() = 0;

protected:
    HINSTANCE m_hInstance;
    HWND m_hWnd;

    D3D_DRIVER_TYPE m_driverType;
    D3D_FEATURE_LEVEL m_featureLevel;

    ID3D11Device* m_pd3dDevice;
    ID3D11DeviceContext* m_pImmediateContext;
    IDXGISwapChain* m_pSwapChain;
    ID3D11RenderTargetView* m_pRenderTargetView;
};

 

Dx11DemoBase.cpp

#include "Dx11DemoBase.h"

Dx11DemoBase::Dx11DemoBase() :m_driverType(D3D_DRIVER_TYPE_NULL), m_featureLevel(D3D_FEATURE_LEVEL_11_0),
m_pd3dDevice(NULL), m_pImmediateContext(NULL), m_pSwapChain(NULL), m_pRenderTargetView(NULL){}

Dx11DemoBase::~Dx11DemoBase()
{
    ShutDown();
}

bool Dx11DemoBase::LoadContent()
{
    return true;
}

void Dx11DemoBase::UnLoadContent()
{

}

void Dx11DemoBase::ShutDown()
{
    UnLoadContent();
    if (m_pRenderTargetView) m_pRenderTargetView->Release();
    if (m_pSwapChain) m_pSwapChain->Release();
    if (m_pd3dDevice) m_pd3dDevice->Release();
    if (m_pImmediateContext) m_pImmediateContext->Release();

    m_pRenderTargetView = NULL;
    m_pSwapChain = NULL;
    m_pd3dDevice = NULL;
    m_pImmediateContext = NULL;
}

//初始化
bool Dx11DemoBase::Initialize(HINSTANCE hInstance, HWND hWnd)
{
    HRESULT result;
    m_hInstance = hInstance;
    m_hWnd = hWnd;
    RECT rc;
    GetClientRect(m_hWnd, &rc);
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    D3D_DRIVER_TYPE driverTypes[] = 
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = m_hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    sd.Windowed = true;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex)
    {
        result = D3D11CreateDeviceAndSwapChain(
            NULL,
            driverTypes[driverTypeIndex],
            NULL,
            createDeviceFlags,
            featureLevels,
            numFeatureLevels,
            D3D11_SDK_VERSION,
            &sd,
            &m_pSwapChain,
            &m_pd3dDevice,
            &m_featureLevel,
            &m_pImmediateContext
            );
        if (SUCCEEDED(result))
        {
            m_driverType = driverTypes[driverTypeIndex];
            break;
        }
    }

    if (FAILED(result))
    {
        return result;
    }

    ID3D11Texture2D *pBackBuffer = NULL;
    result = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);

    if (FAILED(result))
    {
        return result;
    }

    result = m_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &m_pRenderTargetView);
    if (pBackBuffer)
        pBackBuffer->Release();

    if (FAILED(result))
    {
        return result;
    }

    m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);

    D3D11_VIEWPORT vp;
    vp.Height = static_cast<float>(width);//用c++的static_cast转换类型是个好习惯
    vp.Width = static_cast<float>(height);
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0.0f;
    vp.TopLeftY = 0.0f;
    
    m_pImmediateContext->RSSetViewports(1, &vp);

    return LoadContent();
}

 

下面新建一个空白Demo类,这个类没有做什么特别的事,只是用d3d清除了屏幕而已,除了渲染函数,其他所有重写函数都是空的

BlankDemo.h

#pragma once
#include "Dx11DemoBase.h"

class BlankDemo : public Dx11DemoBase
{
public:
    BlankDemo();
    virtual ~BlankDemo();

    bool LoadContent();
    void UnLoadContent();

    void Update(float dt);
    void Render();
};

 

BlankDemo.cpp

#include "BlankDemo.h"


BlankDemo::BlankDemo()
{
}


BlankDemo::~BlankDemo()
{
}

bool BlankDemo::LoadContent()
{
    return true;
}

void BlankDemo::UnLoadContent()
{

}

void BlankDemo::Update(float dt)
{

}

void BlankDemo::Render()
{
    if (!m_pImmediateContext)
        m_pImmediateContext = NULL;
    float clearColors[4] = { 0.0f, 0.0f, 0.5f, 1.0f };
    m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, clearColors);

    m_pSwapChain->Present(0, 0);
}

 

main.cpp

#include <windows.h>
#include <memory>
#include "BlankDemo.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    WNDCLASSEX wcex;
    wcex.cbClsExtra = 0;
    wcex.cbSize = sizeof(wcex);
    wcex.cbWndExtra = 0;
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.hCursor = LoadCursor(NULL,IDC_ARROW);
    wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wcex.hIconSm = wcex.hIcon;
    wcex.hInstance = hInstance;
    wcex.lpfnWndProc = WndProc;
    wcex.lpszClassName = L"BlankDemo";
    wcex.lpszMenuName = L"BlankDemo";
    wcex.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wcex))
        return -1;

    
    RECT rc = { 0, 0, 800, 640 };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);

    HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, L"BlankDemo", L"BlankDemo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
        CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);

    if (!hwnd)
        return -1;

    ShowWindow(hwnd, nShowCmd);

    std::auto_ptr<Dx11DemoBase> demo(new BlankDemo());//使用智能指针

    bool result = demo->Initialize(hInstance, hwnd);
    if (!result)
        return -1;

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        
        demo->Update(0.0f);
        demo->Render();
    }

    demo->ShutDown();
    return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT paintStruct;
    HDC hDc;
    switch (message)
    {
    case WM_PAINT:
        hDc = BeginPaint(hWnd, &paintStruct);
        EndPaint(hWnd, &paintStruct);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

 

运行结果同上次相同

技术分享

以上是关于Directx11学习笔记 封装一个简单的Dx11DemoBase的主要内容,如果未能解决你的问题,请参考以下文章

Directx11学习笔记 将HelloWin封装成类

Directx11学习笔记 基本的数学知识----矩阵篇

DirectX11 学习笔记1 - 第一个程序

Directx11学习笔记十七纹理贴图

DirectX学习笔记:利用D3DX网格数据结构绘制可旋转茶壶

DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记