1. 程式人生 > >Directx11基礎教程二之Directx11初始化

Directx11基礎教程二之Directx11初始化

一,看本節教程前應該掌握:

 

二,程式的結構如下:

      

具體在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庫

五,程式的執行結果如下:


六,原始碼連結如下: