Directx11基礎教程二之Directx11初始化
阿新 • • 發佈:2019-01-28
一,看本節教程前應該掌握:
二,程式的結構如下:
具體在VS2015的程式碼:
三,程式的具體程式碼如下:
好的,下面D3D11的初始化我分為十二個步驟,在原始碼我我做出了標記,其實這跟D3D11龍書給出D3D11初始化的步驟差不多,就是多出了獲取顯示卡資訊的第一步.
好的,先貼出我的D3DClass.H程式碼
D3DClass.h
#ifndef D3D_CLASS_H #define D3D_CLASS_H #define HR(X) {if(FAILED(X)) { MessageBox(0,L"Create Failed",0,0); return false;}} #define ReleaseCOM(x) { if (x) { x->Release(); x = 0; } } #include<Windows.h> #include<d3d11.h> #include<D3Dcommon.h> //??? #include<D3DX11.h> #include<xnamath.h> #include<iostream> #include<istream> #include<ostream> #include<strstream> #include<fstream> using namespace std; class D3DClass { private: bool mVsyncEnable; //是否限幀渲染 int mVideoCardMemory; //顯示卡記憶體 char mVideoCardDescription[128]; //顯示卡名字 private: ID3D11Device* md3dDevice;//D3D11裝置 ID3D11DeviceContext* md3dImmediateContext;//D3D11裝置上下文 IDXGISwapChain* md3dSwapChain;//D3D交換鏈 ID3D11RenderTargetView* md3dRenderTargetView; //D3D11渲染目標檢視 ID3D11DepthStencilView* md3dDepthStencilView; //D3D11深度(模板)檢視 ID3D11Texture2D* md3dDepthStencilBuffer; //D3D11的“DepthStencil快取” ID3D11DepthStencilState* md3dDepthStencilState; //深度(模板)快取狀態 ID3D11RasterizerState* md3dRasterizerState; //D3D的光柵化狀態 private: XMMATRIX mWorldMatrix; //世界變換矩陣 XMMATRIX mOrthoMatrix;; //正交矩陣?? XMMATRIX mProjMatrix; //投影矩陣 public: //構造,拷貝構造,解構函式 D3DClass(); D3DClass(const D3DClass&); ~D3DClass(); //D3DClass初始化函式 bool Initialize(int ScreenWidth, int ScreenHeight, bool vsync, HWND hwnd, bool fullscreen, float ScreenDepth, float ScreenNear); //關閉D3DClass函式 void Shutdown(); //繪製場景函式 void BeginScene(float red, float green, float blue, float alpha); void EndScene(); //Get函式 ID3D11Device* GetDevice() { return md3dDevice; } ID3D11DeviceContext* GetDeviceContext(){ return md3dImmediateContext; } XMMATRIX GetWorldMatrix() { return mWorldMatrix; } XMMATRIX GetOrthoMatrix() { return mOrthoMatrix; } XMMATRIX GetmProjMatrix() { return mProjMatrix; }; void GetVideoCardInfo(char*, int&); //獲取顯示卡資訊 }; #endif // !D3D_CLASS_H
D3DClass.cpp
bool D3DClass::Initialize(int ScreenWidth, int ScreenHeight, bool vsync, HWND hwnd, bool fullscreen, float ScreenDepth, float ScreenNear) { float fieldOfView, screenAspect; //-------------------------------------------------------------- //第一,獲取顯示模式資訊和顯示卡資訊 //--------------------------------------------------------------- IDXGIAdapter* adpter;//介面卡 IDXGIFactory* factory; IDXGIOutput* adapterOutput; unsigned int numModes, numerator, denominator, stringLength; DXGI_MODE_DESC* displayModeList; DXGI_ADAPTER_DESC adapterDesc; int error; //儲存vsyn設定 mVsyncEnable = vsync; //建立一個Directx圖形介面factory HR(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory)); //使用factory來為顯示卡建立一個adapter HR(factory->EnumAdapters(0, &adpter)); //列舉主要的介面卡輸出 HR(adpter->EnumOutputs(0, &adapterOutput)); //獲取適應介面卡DXGI_FORMAT_R8G8B8A8_UNORM顯示格式的模式數目 HR(adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL)); //建立一個顯示模式列表存放可能的顯示模式(顯示卡,監視器) displayModeList= new DXGI_MODE_DESC[numModes]; if (!displayModeList) return false; //填充顯示模式列表結構體 HR(adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList)); //瀏覽所有的顯示模式,找到適合螢幕寬度和高度的 //當一個模式匹配,儲存監視器重新整理速度的分子分母?? for (int i = 0; i<numModes; i++) { if (displayModeList[i].Width == (unsigned int)ScreenWidth) { if (displayModeList[i].Height == (unsigned int)ScreenHeight) { numerator = displayModeList[i].RefreshRate.Numerator; denominator = displayModeList[i].RefreshRate.Denominator; } } } //獲取介面卡(顯示卡)形容 HR(adpter->GetDesc(&adapterDesc)); //獲取顯示卡記憶體量 mVideoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024); //將顯示卡名字轉存在字元陣列 error = wcstombs_s(&stringLength, mVideoCardDescription, 128, adapterDesc.Description, 128); if (error != 0) { return false; } //釋放顯示模式列表 delete[] displayModeList; displayModeList = NULL; ReleaseCOM(adpter); ReleaseCOM(factory); //----------------------------------------------------- //第二,填充交換鍊形容結構體 //----------------------------------------------------- DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferDesc.Width = ScreenWidth; sd.BufferDesc.Height = ScreenHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; if (mVsyncEnable) //限不限幀 { sd.BufferDesc.RefreshRate.Numerator =numerator; sd.BufferDesc.RefreshRate.Denominator = denominator; } else { sd.BufferDesc.RefreshRate.Numerator = 0; sd.BufferDesc.RefreshRate.Denominator = 1; } //關閉多重取樣 sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; //是否進行全屏 if (fullscreen) { sd.Windowed = false; } else { sd.Windowed = true; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; //背後快取數量 sd.OutputWindow = hwnd; //交換鏈所屬的視窗 sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //--------------------------------------------------------------- //第三,建立交換鏈和D3D裝置和D3D裝置上下文 //--------------------------------------------------------------- D3D_FEATURE_LEVEL featureLevel; featureLevel = D3D_FEATURE_LEVEL_11_0; HR(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, D3D11_SDK_VERSION, &sd, &md3dSwapChain, &md3dDevice, NULL, &md3dImmediateContext)); //-------------------------------------------------------------- //第四,建立背後快取檢視 //-------------------------------------------------------------- ID3D11Texture2D*backBuffer; md3dSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); md3dDevice->CreateRenderTargetView(backBuffer, 0, &md3dRenderTargetView); ReleaseCOM(backBuffer); //-------------------------------------------------------------- //第五,填充2DTexture深度快取(模板快取)形容結構體,建立深度快取(模板快取) //-------------------------------------------------------------- D3D11_TEXTURE2D_DESC depthStencilDesc; ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); depthStencilDesc.Width=ScreenWidth; depthStencilDesc.Height = ScreenHeight; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilDesc.SampleDesc.Count = 1; depthStencilDesc.SampleDesc.Quality = 0; depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; HR(md3dDevice->CreateTexture2D(&depthStencilDesc,//要建立的紋理的形容 0, &md3dDepthStencilBuffer)); //指向深度快取的指標 //------------------------------------------------------------- //第六,建立並設定深度快取(模板快取)狀態,指示如何使用Depth和stencil(Test) //------------------------------------------------------------- D3D11_DEPTH_STENCIL_DESC DSDESC; ZeroMemory(&DSDESC, sizeof(DSDESC)); DSDESC.DepthEnable = true; DSDESC.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; DSDESC.DepthFunc = D3D11_COMPARISON_LESS; DSDESC.StencilEnable = true; DSDESC.StencilReadMask = 0xff; DSDESC.StencilWriteMask = 0xff; //前面設定 DSDESC.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; DSDESC.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; DSDESC.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; DSDESC.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; //背面設定,在光柵化狀態剔除背面時這個設定沒用,但是依然要設定,不然無法建立深度(模板)狀態 DSDESC.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; DSDESC.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; DSDESC.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; DSDESC.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; HR(md3dDevice->CreateDepthStencilState(&DSDESC, &md3dDepthStencilState)); md3dImmediateContext->OMSetDepthStencilState(md3dDepthStencilState, 1); //-------------------------------------------------------------- //第七,建立深度快取(模板快取)檢視 //-------------------------------------------------------------- HR(md3dDevice->CreateDepthStencilView( md3dDepthStencilBuffer, //我們基於這個深度快取/漏字板快取建立一個檢視 0, &md3dDepthStencilView));//指向深度快取/漏字板檢視的指標 //------------------------------------------------------------- //第八,把那些檢視繫結到輸出合併階段 //------------------------------------------------------------- md3dImmediateContext->OMSetRenderTargets(1, &md3dRenderTargetView, md3dDepthStencilView); //------------------------------------------------------------- //第九,建立並設定光柵化狀態,用於控制如何渲染目標(以線框還是實體模式等等) //------------------------------------------------------------- D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; //背面剔除 rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; //深度裁剪開啟 rasterDesc.FillMode = D3D11_FILL_SOLID; //實體渲染 rasterDesc.FrontCounterClockwise = false; //順時針 rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; HR(md3dDevice->CreateRasterizerState(&rasterDesc, &md3dRasterizerState)); md3dImmediateContext->RSSetState(md3dRasterizerState); //------------------------------------------------------------- //第十,建立並設定視口 //------------------------------------------------------------- D3D11_VIEWPORT viewport; viewport.Width = static_cast<float>(ScreenWidth); viewport.Height = static_cast<float>(ScreenHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; md3dImmediateContext->RSSetViewports(1, &viewport); //------------------------------------------------------------- //第十一,建立投影矩陣,初始化世界矩陣和使用者介面矩陣 //------------------------------------------------------------- fieldOfView = (float)XM_PI / 4.0f; screenAspect = (float)ScreenWidth / (float)ScreenHeight; //投影矩陣 mProjMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, ScreenNear, ScreenDepth); //世界矩陣 mWorldMatrix = XMMatrixIdentity(); //2D渲染矩陣,用於變換使用者介面,正交投影矩陣 mOrthoMatrix = XMMatrixOrthographicLH(static_cast<float>(ScreenWidth), static_cast<float>(ScreenHeight), ScreenNear, ScreenDepth); //第十二,輸出一個Text檔案儲存顯示卡的資訊 char CardInfo[128]; int memory; GetVideoCardInfo(CardInfo, memory); ofstream os("I:/1.txt"); os << "memory=" << memory << " " << " CardInfo= " << CardInfo; return true; }
四,本節教程程式得注意的地方如下:
(1)D3DClass的初始化第十二步顯示卡資訊的檔案"1.txt"輸出在我的I盤上,這點大家請注意根據自己情況修改.
(2) 我用的是 xnamath.h 數學庫,並非原作者的 d3dx10math.h庫