D3D初始化窗口显示

//代码来源于教材(重庆大学---基于Dx11的案例教程)
#pragma
once #include <iostream> #include<d3dcompiler.h> #include <DirectXMath.h> #include<d3d11.h> #include<dxgi.h> using namespace DirectX; namespace d3d { bool initD3D(HINSTANCE hinstance, int W, int H, ID3D11RenderTargetView** renderTarview,//目标渲染视图接口 ID3D11DeviceContext** immCtx, IDXGISwapChain** swapChain, ID3D11Device** device //设备,至少一个设备 ); int EnterMsgLoop(bool (*ptr)(float timeDelta)); LRESULT CALLBACK WndProc(HWND,UINT msg,WPARAM,LPARAM Iparam); }
#include "d3dinit.h"

bool d3d::initD3D(HINSTANCE hinstance, int W, int H, ID3D11RenderTargetView** renderTarview, ID3D11DeviceContext** immCtx, IDXGISwapChain** swapChain, ID3D11Device** device)
{
    //窗口类实例
    WNDCLASS wnd;
    wnd.style = CS_HREDRAW | CS_VREDRAW;//窗口风格
    wnd.lpfnWndProc = d3d::WndProc;//窗口回调
    wnd.cbClsExtra = 0;//窗口类附加内存
    wnd.cbWndExtra = 0;//窗口附加内存
    wnd.hInstance = hinstance;//实例句柄
    wnd.hIcon = LoadIcon(0, IDI_APPLICATION);//图标句柄
    wnd.hCursor = LoadCursor(0, IDC_ARROW);//光标句柄--此时为默认箭头光标
    wnd.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//背景画刷句柄--(HBRUSH)为强制类型转换
    wnd.lpszMenuName = 0;//菜单名字
    wnd.lpszClassName = L"D3D TEST";//窗口类名

    //注册窗口
    if (!RegisterClass(&wnd))
    {
        MessageBox(0, L"Register d3d Windows Failed !", L"Warning !", 0);
        return false;
    }
    //创建窗口
    HWND hwnd = 0;
    hwnd = ::CreateWindow(L"D3D TEST", L"D3D11",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, W, H, 0, 0, hinstance, 0);
    if (!hwnd)
    {
        MessageBox(0, L"create d3d!", L"Warning !", 0);
        return false;
    }
    ::ShowWindow(hwnd,SW_SHOW);
    ::UpdateWindow(hwnd);
    //交换链的描述
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd,sizeof(sd));
    sd.BufferCount = 1;//后缓冲数量
    sd.BufferDesc.Width = W;
    sd.BufferDesc.Height = H;
    sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;//24bit RGB
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hwnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = true;
    //创建设备,交换链,上下文
    D3D_FEATURE_LEVEL featurelevs[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,

    };
    UINT NUM_featurelevel = ARRAYSIZE(featurelevs);
    //创建设备和交换链
    if (FAILED(D3D11CreateDeviceAndSwapChain(
        NULL,                       //确定显示适配器,NULL表示默认显示适配器
        D3D_DRIVER_TYPE_HARDWARE,   //选择驱动类型,这里表示使用三维硬件加速
        NULL,                       //只有上一个参数设置D3D_DRIVER_TYPE_SOFTWARE时,才使用这个参数
        0,                          //也可以设置为D3D11_CREATE_DEVICE_DEBUG开启调试模式
        featurelevs,              //前面定义的D3D_FEATURE_LEVEL数组
        NUM_featurelevel,           //D3D_FEATURE_LEVEL的元素个数
        D3D11_SDK_VERSION,          //SDK的版本,这里为D3D11
        &sd,                        //前面定义的DXGI_SWAP_CHAIN_DESC对象
        swapChain,                  //返回创建好的交换链指针,InitD3D函数传递的实参
        device,                     //返回创建好的设备用指针,InitD3D函数传递的实参
        NULL,                       //返回当前设备支持的featureLevels数组中的第一个对象,一般设置为NULL
        immCtx)))      //返回创建好的设备上下文指针,InitD3D函数传递的实参
    {
        ::MessageBox(0, L"CreateDevice and swapchain - FAILED", 0, 0);  //如果创建失败,弹出消息框
        return false;
    }
    //设置渲染目标视图
    HRESULT hr = 0;
    ID3D11Texture2D* pbackBuf = NULL;//surface
    //调用GetBuffer()函数得到后台缓存对象,并存入&pBackBuffer中
    hr = (*swapChain)->GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&pbackBuf);
    if (FAILED(hr))
    {
        ::MessageBox(0, L"GetBuffer - FAILED", 0, 0); //如果调用失败,弹出消息框
        return false;
    }
    //创建渲染目标视图
    hr = (*device)->CreateRenderTargetView(pbackBuf,NULL,renderTarview);
    pbackBuf->Release();
    //判断CreateRenderTargetView是否调用成功
    if (FAILED(hr))
    {
        ::MessageBox(0, L"CreateRender - FAILED", 0, 0);  //如果调用失败,弹出消息框
        return false;
    }
    //渲染目标视图绑定到渲染管线上
    (*immCtx)->OMSetRenderTargets(1, // 绑定的目标视图的个数
        renderTarview,NULL);// //设置为NULL表示不绑定深度模板

    //第四步,设置视口大小,D3D11默认不会设置视口,此步骤必须手动设置

    D3D11_VIEWPORT vp;    //创建一个视口的对象
    vp.Width = W;         //视口的宽
    vp.Height = H;        //视口的高
    vp.MinDepth = 0.0f;   //深度值的下限,**由于深度值是[0, 1]所以下限值是0
    vp.MaxDepth = 1.0f;   //深度值的上限,上限值是1
    vp.TopLeftX = 0;      //视口左上角的横坐标
    vp.TopLeftY = 0;      //视口左上角的总坐标

    //设置视口
    (*immCtx)->RSSetViewports(1,     //视口的个数
        &vp); //上面创建的视口对象

    return true;
    
}

int d3d::EnterMsgLoop(bool(*ptr)(float timeDelta))
{
    MSG msg;
    ::ZeroMemory(&msg, sizeof(MSG));                  //初始化内存

    static float lastTime = (float)timeGetTime();     //第一次获取当前时间

    while (msg.message != WM_QUIT)
    {
        if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
        else
        {
            float currTime = (float)timeGetTime();            //第二次获取当前时间
            float timeDelta = (currTime - lastTime) * 0.001f;    //获取两次时间之间的时间差

            ptr(timeDelta);    //调用显示函数,这在后面实现图形的变化(如旋转)时会用到

            lastTime = currTime;
        }
    }
    return msg.wParam;

    
}
// D3Dtest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "d3dinit.h"

ID3D11Device* device = NULL;                    //D3D11设备指针
IDXGISwapChain* swapChain = NULL;               //交换链指针
ID3D11DeviceContext* immediateContext = NULL;   //设备上下文指针
ID3D11RenderTargetView* renderTargetView = NULL;//渲染目标视图指针  

void Cleanup()
{
    //释放指针
    if (renderTargetView) renderTargetView->Release();
    if (immediateContext) immediateContext->Release();
    if (swapChain)        swapChain->Release();
    if (device)           device->Release();
}
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);

}

bool Display(float timeDelta)
{
    if (device)
    {
        //声明一个数组存放颜色信息,4个元素分别表示红,绿,蓝以及alpha
        float ClearColor[4] = { 0.3f, 0.5f, 0.6f, 1.0f };
        //清除渲染目标视图
        immediateContext->ClearRenderTargetView(renderTargetView, ClearColor);
        //显示渲染好的图像
        swapChain->Present(0,  //指定如何同步显示,设置0表示不同步显示
            0);//可选项,设置0表示为从每个缓存中显示一帧
    }
    return true;

}
int WINAPI WinMain(HINSTANCE hinstance,
    HINSTANCE prevInstance,
    PSTR cmdLine,
    int showCmd)
{
    //初始化
    //**注意**:最上面声明的4个指针,在这里作为参数传给InitD3D函数
    if (!d3d::initD3D(hinstance,
        800,
        600,
        &renderTargetView,
        &immediateContext,
        &swapChain,
        &device))
    {
        ::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
        return 0;
    }

    

    //执行消息循环,将函数Display的指针作为参数传递
    d3d::EnterMsgLoop(Display);

    Cleanup();

    return 0;

}

注意创建窗口程序:vs2022

 

 

 

posted on 2025-07-21 17:10  邗影  阅读(17)  评论(0)    收藏  举报

导航