dx11学习笔记-1.创建一个空窗口

来源:互联网 发布:向量化编程为何快 编辑:程序博客网 时间:2024/06/10 08:38

资料:
Microsoft DirectX SDK (June 2010) source code&document
《DX11游戏编程入门》source code&pdf

基本流程

1、初始化dx环境:

最基本的三个变量

ID3D11Device* g_pd3dDevice = NULL;
ID3D11DeviceContext* g_pImmediateContext = NULL;
IDXGISwapChain* g_pSwapChain = NULL;

In Direct3D 10, the device object was used to perform both rendering and resource creation. In Direct3D 11, the immediate context is used by the application to perform rendering onto a buffer, and the device contains methods to create resources.
也就是说,device负责创建各种资源,context负责渲染。而swapchain管理着渲染的“画布”——缓存。
更进一步解释,device负责着dx和硬件之间的通信,context负责告诉device渲染是怎么个设置,保存着渲染的状态信息,而swapchain可以看做渲染的目标。

缓存:就是存放数据的一块空间,一块具有固定尺寸的内存。比如光栅屏幕缓存其实是个二维数组,每个像素的信息就是缓存中一个元素。所谓渲染到缓存上,其实是用计算得到的颜色值去填充每一个像素。

其他必需变量

ID3D11RenderTargetView* g_pRenderTargetView = NULL;

DX中我们通过调用swapChain的GetBuffer方法来得到其管理的缓存地址,得到缓存地址后,作为参数传入device调用的CreateRenderTargetView方法,创建并保存到g_pRenderTargetView 。我们通过变量获取的缓存指针此时便没有用处了,需要及时调用Release方法将其占用资源释放,否则会发生内存泄露。
此处《DX11游戏编程》的解释为:当我们获得一个COM对象的引用时,该对象的引用数+1,确定该对象不会被再次调用时,需要调用COM对象的Release函数将该对象的引用数-1。当COM对象的引用数为0时,就会被删除。
相关知识可查阅“缓存池”

现在我们有了渲染目标g_pRenderTargetView ,那就需要告诉context这目标是谁。调用context的OMSetRenderTargets方法,传入g_pRenderTargetView 即可关联二者。

接下来,继续为context设置渲染的各个属性。
渲染在什么区域?调用context的RSSetViewports方法。此处viewport设置了渲染视口的长宽、渲染的左上角对应在窗口内屏幕的XY坐标,和需要渲染的最大最小深度。如果XY坐标都设为0,那么渲染视口左上角就与客户区窗口左上角重合。

2、渲染:

context调用ClearRenderTargetView方法来设置用于更新缓存的基本颜色;
swapChain调用Present来重绘。

3、清理:

按照从子对象到父对象的顺序,调用COM对象的Release方法,将其释放。
注意释放前需要检查指针是否存在,如果对不存在的对象指针调用其方法,会产生不可预料的后果。

完整代码

见Microsoft DirectX SDK (June 2010) Tutorial01

//--------------------------------------------------------------------------------------// File: Tutorial01.cpp//// This application demonstrates creating a Direct3D 11 device//// Copyright (c) Microsoft Corporation. All rights reserved.//--------------------------------------------------------------------------------------#include <windows.h>#include <d3d11.h>#include <d3dx11.h>#include "resource.h"//--------------------------------------------------------------------------------------// Global Variables//--------------------------------------------------------------------------------------HINSTANCE               g_hInst = NULL;HWND                    g_hWnd = NULL;D3D_DRIVER_TYPE         g_driverType = D3D_DRIVER_TYPE_NULL;D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;ID3D11Device*           g_pd3dDevice = NULL;ID3D11DeviceContext*    g_pImmediateContext = NULL;IDXGISwapChain*         g_pSwapChain = NULL;ID3D11RenderTargetView* g_pRenderTargetView = NULL;//--------------------------------------------------------------------------------------// Forward declarations//--------------------------------------------------------------------------------------HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );HRESULT InitDevice();void CleanupDevice();LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );void Render();//--------------------------------------------------------------------------------------// Entry point to the program. Initializes everything and goes into a message processing // loop. Idle time is used to render the scene.//--------------------------------------------------------------------------------------int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){    UNREFERENCED_PARAMETER( hPrevInstance );    UNREFERENCED_PARAMETER( lpCmdLine );    if( FAILED( InitWindow( hInstance, nCmdShow ) ) )        return 0;    if( FAILED( InitDevice() ) )    {        CleanupDevice();        return 0;    }    // Main message loop    MSG msg = {0};    while( WM_QUIT != msg.message )    {        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )        {            TranslateMessage( &msg );            DispatchMessage( &msg );        }        else        {            Render();        }    }    CleanupDevice();    return ( int )msg.wParam;}//--------------------------------------------------------------------------------------// Register class and create window//--------------------------------------------------------------------------------------HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){    // Register class    WNDCLASSEX wcex;    wcex.cbSize = sizeof( WNDCLASSEX );    wcex.style = CS_HREDRAW | CS_VREDRAW;    wcex.lpfnWndProc = WndProc;    wcex.cbClsExtra = 0;    wcex.cbWndExtra = 0;    wcex.hInstance = hInstance;    wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );    wcex.lpszMenuName = NULL;    wcex.lpszClassName = L"TutorialWindowClass";    wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );    if( !RegisterClassEx( &wcex ) )        return E_FAIL;    // Create window    g_hInst = hInstance;    RECT rc = { 0, 0, 640, 480 };    AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );    g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 1: Direct3D 11 Basics", WS_OVERLAPPEDWINDOW,                           CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,                           NULL );    if( !g_hWnd )        return E_FAIL;    ShowWindow( g_hWnd, nCmdShow );    return S_OK;}//--------------------------------------------------------------------------------------// Called every time the application receives a message//--------------------------------------------------------------------------------------LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){    PAINTSTRUCT ps;    HDC hdc;    switch( message )    {        case WM_PAINT:            hdc = BeginPaint( hWnd, &ps );            EndPaint( hWnd, &ps );            break;        case WM_DESTROY:            PostQuitMessage( 0 );            break;        default:            return DefWindowProc( hWnd, message, wParam, lParam );    }    return 0;}//--------------------------------------------------------------------------------------// Create Direct3D device and swap chain//--------------------------------------------------------------------------------------HRESULT InitDevice(){    HRESULT hr = S_OK;    RECT rc;    GetClientRect( g_hWnd, &rc );    UINT width = rc.right - rc.left;    UINT height = rc.bottom - rc.top;    UINT createDeviceFlags = 0;#ifdef _DEBUG    //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;#endif    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 = g_hWnd;    sd.SampleDesc.Count = 1;    sd.SampleDesc.Quality = 0;    sd.Windowed = TRUE;    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )    {        g_driverType = driverTypes[driverTypeIndex];        hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,                                            D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );        if( SUCCEEDED( hr ) )            break;    }    if( FAILED( hr ) )        return hr;    // Create a render target view    ID3D11Texture2D* pBackBuffer = NULL;    hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );    if( FAILED( hr ) )        return hr;    hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );    pBackBuffer->Release();    if( FAILED( hr ) )        return hr;    g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );    // Setup the viewport    D3D11_VIEWPORT vp;    vp.Width = (FLOAT)width;    vp.Height = (FLOAT)height;    vp.MinDepth = 0.0f;    vp.MaxDepth = 1.0f;    vp.TopLeftX = 0;    vp.TopLeftY = 0;    g_pImmediateContext->RSSetViewports( 1, &vp );    return S_OK;}//--------------------------------------------------------------------------------------// Render the frame//--------------------------------------------------------------------------------------void Render(){    // Just clear the backbuffer    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha    g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );    g_pSwapChain->Present( 0, 0 );}//--------------------------------------------------------------------------------------// Clean up the objects we've created//--------------------------------------------------------------------------------------void CleanupDevice(){    if( g_pImmediateContext ) g_pImmediateContext->ClearState();    if( g_pRenderTargetView ) g_pRenderTargetView->Release();    if( g_pSwapChain ) g_pSwapChain->Release();    if( g_pImmediateContext ) g_pImmediateContext->Release();    if( g_pd3dDevice ) g_pd3dDevice->Release();}
0 0
原创粉丝点击