首页 > 代码库 > DirectX11 学习笔记4 - 一个完整的封装框架

DirectX11 学习笔记4 - 一个完整的封装框架


本程序主要由5个文件组成。1个CPP 4个H文件  本来H文件可以分为4个CPP4个H,但是感觉太多了,就写到一起了

XMain 

这个文件就是windows程序的入口函数

<span style="font-size:14px;">//入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) 
{

	XWindow *xwindow=new XWindow;
	xwindow->init(); //初始化
	xwindow->close();
	delete xwindow;
	return 0; 
}</span>

接下来就是进入XWindow.h 

XWindow.h

首先是init()

xwidth=500;
	xheight=400;
	x_input=new XInput;
	x_graphics=new XGraphics;
	
	//创建窗口
	initWindows(xwidth,xheight,L"Engine");
	//初始化键盘
	x_input->init();
	//初始化渲染
	x_graphics->init(xwidth,xheight,m_hwnd);


	//消息循环
	runWindows();
	//关闭窗口
	closeWindows();
主要就是创建了 窗口,键初始化,渲染初始化。 然后就可以开始我们的消息循环了。

窗口初始化学过windows编程的就知道比较简单,然后x_input后面讲。

唯一与Directx相关的就是消息循环和渲染了。

其中消息循环:

MSG msg; 
	// 初始化消息结构. 
	ZeroMemory(&msg, sizeof(MSG));
	// 循环进行消息处理
	while(!Xexit) 
	{ 
		// 处理windows消息. 
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
		{ 
			TranslateMessage(&msg); 
			DispatchMessage(&msg); 
		}
		// 接收到WM_QUIT消息,退出程序. 
		if(msg.message == WM_QUIT) 
		{ 
			Xexit=true;
		} 
		else 
		{ 
			//渲染
			Xexit=!frame();
		}

	}

加了一个frame函数, 意思就是除了接受windows的正常消息之外。还不断的循环着一个函数frame. 

这个frame就是渲染有关的啦。

bool XWindow::frame()
{
	//判断是否按下ESC键
	if(x_input->isKeyDown(VK_ESCAPE))
		return false;
	//开始渲染
	return x_graphics->frame();
}

bool XGraphics::frame() 
{
	bool hr=render();
	return hr; 
}
bool XGraphics::render() 
{
	x_d3d->begin(0.0f,0.0f,0.5f,1.0f);//蓝色
	x_d3d->end();
	return true; 
}

如上面一层一层的调用。其实最终就是绘制了一个蓝色的背景。之所以写这么多层,而不在一个程序里2行代码搞定,是因为之后的工程越来越大,全部放一个文件,会非常难分析其逻辑,而且非常难修改。

XGraphics

以后主要代码就是写在这个类里面了,现在还是空空的。

XD3Device

这个类就是做这个框架的意义了。

里面的init() 初始化了一堆很复杂,很烦躁的。  设备链,深度模板缓冲,各种状态绑定等等。都是一次性的。后面只需要改改参数就行。所以把它隔离到这个类。

只要在用的时候轻轻调用一个函数就可以了

bool XGraphics:: init(int screenWidth, int screenHeight, HWND hwnd) 
{
	x_d3d=new XD3Device;
	bool hr=x_d3d->init(screenWidth,screenHeight,VSYNC_ENABLED,hwnd,FULL_SCREEN,SCREEN_DEPTH,SCREEN_NEAR);
	if(!hr)
	{
		MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK); 
		return false; 
	}
	return true; 
}


全部代码

XGraphics.h

效果

#pragma once

#include <windows.h>
#include "XD3Device.h"
///////////// 
// GLOBALS // 
///////////// 
const bool  FULL_SCREEN = false; //是否全屏 
const bool  VSYNC_ENABLED = true; //是否垂直同步 
const float SCREEN_DEPTH = 1000.0f; //深度,远点 
const float SCREEN_NEAR = 0.1f; //深度,近点

class XGraphics 
{ 
public: 
	bool init(int, int, HWND); //初始化渲染设备
	void close(); 
	bool frame();

private: 
	bool render(); 
private:
	XD3Device *x_d3d;
};

bool XGraphics:: init(int screenWidth, int screenHeight, HWND hwnd) 
{
	x_d3d=new XD3Device;
	bool hr=x_d3d->init(screenWidth,screenHeight,VSYNC_ENABLED,hwnd,FULL_SCREEN,SCREEN_DEPTH,SCREEN_NEAR);
	if(!hr)
	{
		MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK); 
		return false; 
	}
	return true; 
}

void XGraphics::close() 
{
	if(x_d3d)
	{
		x_d3d->close();
		delete x_d3d;
		x_d3d=0;
	}
}

bool XGraphics::frame() 
{
	bool hr=render();
	return hr; 
}


bool XGraphics::render() 
{
	x_d3d->begin(0.0f,0.0f,0.5f,1.0f);//蓝色
	x_d3d->end();
	return true; 
}

XWindows.h

#pragma once 
//定义该宏能够减少windows头文件的大小,使编译器不编译一些不必要的文件,加快编译时间 
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "XGraphics.h"
#include "XInput.h"
//退出
static bool Xexit=false;
//全屏
static bool fullScreen=false;
class XWindow
{
private:
	//窗口类名字
	LPCWSTR m_applicationName;
	//实例句柄
	HINSTANCE m_hinstance;
	//窗口句柄
	HWND m_hwnd;
	int xwidth,xheight;
	//按键类
	XInput * x_input;
	//图形类
	XGraphics * x_graphics;
private:
	//初始化窗口
	void initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName);
	//关闭窗口
	void closeWindows();
	//消息循环
	void runWindows();
	
public:
	//初始化全局
	virtual void init();
	//渲染
	virtual bool frame();
	//退出
	virtual void close();
	//消息函数
	LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM); 
};
//消息循环回调函数
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static XWindow * appXWindow=NULL;
void XWindow::close()
{
	if(x_input)
	{
		delete x_input;
		x_input=NULL;
	}
	if(x_graphics)
	{
		x_graphics->close();
		delete x_graphics;
		x_graphics=NULL;
	}
}
void XWindow::init()
{
	xwidth=500;
	xheight=400;
	x_input=new XInput;
	x_graphics=new XGraphics;
	
	//创建窗口
	initWindows(xwidth,xheight,L"Engine");
	//初始化键盘
	x_input->init();
	//初始化渲染
	x_graphics->init(xwidth,xheight,m_hwnd);


	//消息循环
	runWindows();
	//关闭窗口
	closeWindows();
}
bool XWindow::frame()
{
	//判断是否按下ESC键
	if(x_input->isKeyDown(VK_ESCAPE))
		return false;
	//开始渲染
	return x_graphics->frame();
}
void XWindow::initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName)
{
	WNDCLASSEX wc; 
	DEVMODE dmScreenSettings; 
	int posX, posY;
	this->m_applicationName=m_applicationName;
	// 得到应用程序实例句柄 
	m_hinstance = GetModuleHandle(NULL);
	appXWindow=this;
	// 设置窗口类参数. 
	wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 

	wc.lpfnWndProc   = WndProc; //指定回调函数 
	wc.cbClsExtra    = 0; 
	wc.cbWndExtra    = 0; 
	wc.hInstance     = m_hinstance; 
	wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO); 
	wc.hIconSm       = wc.hIcon; 
	wc.hCursor       = LoadCursor(NULL, IDC_ARROW); 
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //默认黑色窗口黑色背景 
	wc.lpszMenuName  = NULL; 
	wc.lpszClassName = m_applicationName; 
	wc.cbSize        = sizeof(WNDCLASSEX);

	// 注册窗口类 
	RegisterClassEx(&wc);

	// 根据是否全屏设置不同的分辨率. 
	if(fullScreen) 
	{ 
		// 得到windows桌面分辨率 
		screenWidth  = GetSystemMetrics(SM_CXSCREEN); 
		screenHeight = GetSystemMetrics(SM_CYSCREEN);
		//全屏模式下,设置窗口大小为windows桌面分辨率. 
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); 
		dmScreenSettings.dmSize       = sizeof(dmScreenSettings); 
		dmScreenSettings.dmPelsWidth  = (unsigned long)screenWidth; 
		dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight; 
		dmScreenSettings.dmBitsPerPel = 32;            
		dmScreenSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		// 临时设置显示设备为全屏模式,注意:应用程序退出时候,将恢复系统默认设置。 
		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);

		// 设置窗口的左上角坐标位置为(0,0). 
		posX = posY = 0; 
	} 
	else 
	{ 
		// 窗口左上角坐标位置,posX, posY
		posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth)  / 2; 
		posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2; 
	}

	// 全屏和窗口使用不同的参数. 
	if( fullScreen) 
	{ 
		m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
			WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, 
			posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); 
	} 
	else 
	{ 
		m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, 
			WS_OVERLAPPEDWINDOW, 
			posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); 
	}

	// 显示窗口并设置其为焦点. 
	ShowWindow(m_hwnd, SW_SHOW); 
	SetForegroundWindow(m_hwnd); 
	SetFocus(m_hwnd);
	// 隐藏鼠标. 
	//ShowCursor(false);

}

void XWindow::runWindows()
{
	MSG msg; 
	// 初始化消息结构. 
	ZeroMemory(&msg, sizeof(MSG));
	// 循环进行消息处理
	while(!Xexit) 
	{ 
		// 处理windows消息. 
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
		{ 
			TranslateMessage(&msg); 
			DispatchMessage(&msg); 
		}
		// 接收到WM_QUIT消息,退出程序. 
		if(msg.message == WM_QUIT) 
		{ 
			Xexit=true;
		} 
		else 
		{ 
			//渲染
			Xexit=!frame();
		}

	}
	return; 
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam) 
{ 
	switch(umessage) 
	{

		// 窗口销毁消息. 
	case WM_DESTROY: 
	case WM_CLOSE: 
		{ 
			PostQuitMessage(0); 
			return 0; 
		}
		break;
		//MessageHandle过程处理其它所有消息. 
	default: 
		{ 
			return appXWindow->MessageHandler(hwnd, umessage, wparam, lparam); 
		} 
		break;
	} 

}

LRESULT CALLBACK XWindow::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) 
{

	switch(umsg) 
	{ 
		// 检测按键消息. 
	case WM_KEYDOWN: 
		x_input->keyDown(wparam);
	    break;
	case WM_KEYUP:
		x_input->keyUp(wparam);
		break;
		//任何其它消息发送到windows缺省处理. 
	default: 
		{ 
			return DefWindowProc(hwnd, umsg, wparam, lparam); 
		} 
	} 
	return 0;
}
void XWindow::closeWindows()
{
	//显示光标. 
	//ShowCursor(true);
	// 恢复默认显示设置. 
	if(fullScreen) 
	{ 
		ChangeDisplaySettings(NULL, 0); 
	}
	//释放窗口句柄. 
	DestroyWindow(m_hwnd); 
	m_hwnd = NULL;
	// 释放应用程序实例. 
	UnregisterClass(m_applicationName, m_hinstance); 
	m_hinstance = NULL;
	appXWindow=NULL;
	return; 
}

XInput.h

#pragma once
class XInput
{
public:
	void init();
	void keyDown(unsigned int);
	void keyUp(unsigned int);
	bool isKeyDown(unsigned int);
private:
	bool x_keys[256];

};
void XInput::init()
{
	int i;

	// 初始所有的键都是非按下状态. 
	for(i=0; i<256; i++) 
	{ 
		x_keys[i] = false; 
	}

	return; 
}
void XInput::keyDown(unsigned int input) 
{ 
	//键被按下. 
	x_keys[input] = true; 
	return; 
}
void XInput::keyUp(unsigned int input) 
{ 
	//键被按下. 
	x_keys[input] = false; 
	return; 
}
bool XInput::isKeyDown(unsigned int key) 
{ 
	// 判断键是否被按下? 
	return x_keys[key]; 
}

XMain.cpp

#include "XWindow.h"
//入口
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) 
{

	XWindow *xwindow=new XWindow;
	xwindow->init(); //初始化
	xwindow->close();
	delete xwindow;
	return 0; 
}

XD3Device.h


</pre><pre name="code" class="cpp">#pragma once
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")
#include <dxgi.h>
#include <d3dcommon.h>
#include <d3d11.h>
#include <d3dx10math.h>
#include <xnamath.h>
class XD3Device
{
public:
	XD3Device();
	//3D设备所有初始化
	bool init(int, int, bool, HWND, bool, float, float);
	//关闭设备
	void close();
	//开始渲染设备
	void begin(float, float, float, float);
	//显示到前景
	void end();

public:
	bool m_vsync_enabled; //是否启用垂直同步
	IDXGISwapChain* m_swapChain; //交换链对象
	ID3D11Device* m_device;  //设备对象
	ID3D11DeviceContext* m_deviceContext; //设备上下文对象
	ID3D11RenderTargetView* m_renderTargetView; //渲染目标视图
	ID3D11Texture2D* m_depthStencilBuffer; //深度模板缓冲
	ID3D11DepthStencilState* m_depthStencilState; //深度磨成状态
	ID3D11DepthStencilView* m_depthStencilView; //深度目标视图
	ID3D11RasterizerState* m_rasterState; //光栅化状态
	D3DXMATRIX m_projectionMatrix; //投影矩阵
	D3DXMATRIX m_worldMatrix;//世界坐标系矩阵
	D3DXMATRIX m_orthoMatrix;//正交投影矩阵
};
void XD3Device::begin(float red, float green, float blue, float alpha)
{
	float color[]={red,green,blue,alpha};
	//清除后缓冲.
	m_deviceContext->ClearRenderTargetView(m_renderTargetView, color);

	//清除深度缓冲.
	m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

}
void XD3Device::end()
{
	//渲染完成后,把后缓冲内容present到前缓冲
	if(m_vsync_enabled)
	{
		// 锁定屏幕刷新率.
		m_swapChain->Present(1, 0);
	}
	else
	{
		// 尽可能快的present后缓冲.
		m_swapChain->Present(0, 0);
	}

}
void XD3Device::close()
{
	// 释放交换链资源前,先设置为窗口模式,否则可能会产生异常.
	if(m_swapChain)
	{
		m_swapChain->SetFullscreenState(false, NULL);
	}

	if(m_rasterState)
	{
		m_rasterState->Release();
		m_rasterState = 0;
	}

	if(m_depthStencilView)
	{
		m_depthStencilView->Release();
		m_depthStencilView = 0;
	}

	if(m_depthStencilState)
	{
		m_depthStencilState->Release();
		m_depthStencilState = 0;
	}

	if(m_depthStencilBuffer)
	{
		m_depthStencilBuffer->Release();
		m_depthStencilBuffer = 0;
	}

	if(m_renderTargetView)
	{
		m_renderTargetView->Release();
		m_renderTargetView = 0;
	}

	if(m_deviceContext)
	{
		m_deviceContext->Release();
		m_deviceContext = 0;
	}

	if(m_device)
	{
		m_device->Release();
		m_device = 0;
	}

	if(m_swapChain)
	{
		m_swapChain->Release();
		m_swapChain = 0;
	}

}
XD3Device::XD3Device()
{
	m_swapChain = 0;
	m_device = 0;
	m_deviceContext = 0;
	m_renderTargetView = 0;
	m_depthStencilBuffer = 0;
	m_depthStencilState = 0;
	m_depthStencilView = 0;
	m_rasterState = 0;
}
//Initialize函数包含完成D3D设置的所有代码。
bool XD3Device::init(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, 
						  float screenDepth, float screenNear)
{
	HRESULT result;
	IDXGIFactory* factory;
	IDXGIAdapter* adapter;
	IDXGIOutput* adapterOutput;
	unsigned int numModes, i, stringLength;
	DXGI_MODE_DESC* displayModeList;
	DXGI_ADAPTER_DESC adapterDesc;
	int error;
	DXGI_SWAP_CHAIN_DESC swapChainDesc;
	D3D_FEATURE_LEVEL featureLevel;
	ID3D11Texture2D* backBufferPtr;
	D3D11_TEXTURE2D_DESC depthBufferDesc;
	D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
	D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
	D3D11_RASTERIZER_DESC rasterDesc;
	D3D11_VIEWPORT viewport;
	float fieldOfView, screenAspect;


	// 保存垂直同步设置
	m_vsync_enabled = vsync;

	// 初始化交换链描述
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
	//MessageBox(hwnd, L"Could 2", L"Error", MB_OK); 
	// 用1个后缓冲
	swapChainDesc.BufferCount = 1;

	//帧缓冲的大小和应用程序窗口大小相等.
	swapChainDesc.BufferDesc.Width = screenWidth;
	swapChainDesc.BufferDesc.Height = screenHeight;

	// 后缓冲的surface的格式为DXGI_FORMAT_R8G8B8A8_UNORM.
	// surface的每个像素用4个无符号的8bit[映射到0-1]来表示。NORM表示归一化。
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

	// 如果使用垂直同步,设置后缓冲的刷新率。.
	//刷新率就是一秒钟把后缓冲内容在屏幕上画出的次数。
	//如果开启垂直同步,则锁定刷新率,则fps是固定的
	if(m_vsync_enabled)
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}
	else
	{
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	}

	// 设置后缓冲的用途
	// 我们的渲染目标缓冲为后缓冲。
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

	// 后缓冲输出的窗口句柄.
	swapChainDesc.OutputWindow = hwnd;

	// 不使用多重采样
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;

	// 设置全屏或者窗口模式.
	if(fullscreen)
	{
		swapChainDesc.Windowed = false;
	}
	else
	{
		swapChainDesc.Windowed = true;
	}
	//MessageBox(hwnd, L"Could 1", L"Error", MB_OK); 
	// 设定扫描线ordering以及缩放为unspecified.
	swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

	// 后缓冲内容呈现到屏幕后,放弃其内容
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

	//不设置标志
	swapChainDesc.Flags = 0;

	// 设置feature level为D3D11
	// 如果显卡不支持D3D11,我们能够通过设置这个参数,使用D3D10,或者9.
	//featureLevel = D3D_FEATURE_LEVEL_10_1;
	D3D_FEATURE_LEVEL featureLevels[] =
	{
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
	};
	UINT numFeatureLevels = ARRAYSIZE( featureLevels );
	// 创建交换链,设备以及设备上下文.
	result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, numFeatureLevels, 
		D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);
	//MessageBox(hwnd, L"Could 1", L"Error", MB_OK); 
	if(FAILED(result))
	{
		return false;
	}

	// 得到交换链中的后缓冲指针.
	result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
	if(FAILED(result))
	{
		return false;
	}

	// 用后缓冲创建渲染目标视图.
	result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
	if(FAILED(result))
	{
		return false;
	}

	//释放后缓冲.(引用计数减1)
	backBufferPtr->Release();
	backBufferPtr = 0;

	// 初始化深度缓冲描述.
	ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

	//设置深度缓冲描述
	depthBufferDesc.Width = screenWidth;
	depthBufferDesc.Height = screenHeight;
	depthBufferDesc.MipLevels = 1;//对于深度缓冲为1
	depthBufferDesc.ArraySize = 1;//对于深度缓冲为1,对于纹理,这2个参数有更多用途
	depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthBufferDesc.SampleDesc.Count = 1;
	depthBufferDesc.SampleDesc.Quality = 0;
	depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	depthBufferDesc.CPUAccessFlags = 0;
	depthBufferDesc.MiscFlags = 0;

	// 创建深度缓冲.
	result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
	if(FAILED(result))
	{
		return false;

	}

	// 初始化深度模版状态描述.
	ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));

	// 设置深度模版状态描述.
	depthStencilDesc.DepthEnable = true;
	depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;//D3D11_DEPTH_WRITE_MASK_ZERO禁止写深度缓冲
	depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

	depthStencilDesc.StencilEnable = true;
	depthStencilDesc.StencilReadMask = 0xFF;
	depthStencilDesc.StencilWriteMask = 0xFF;

	// 对于front face 像素使用的模版操作操作.
	depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
	depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	// 对于back face像素使用的模版操作模式.
	depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
	depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	// 创建深度模版状态,使其生效
	result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
	if(FAILED(result))
	{
		return false;

	}

	// 设置深度模版状态.
	m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);

	// 初始化深度模版视图.
	ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

	// 设置深度模版视图描述.
	depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
	depthStencilViewDesc.Texture2D.MipSlice = 0;

	// 创建深度模版视图.
	result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
	if(FAILED(result))
	{
		return false;
	}

	// 绑定渲染目标视图和深度缓冲到渲染管线.
	m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);


	// 设置光栅化描述,指定多边形如何被渲染.
	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;

	// 创建光栅化状态
	result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
	if(FAILED(result))
	{
		return false;
	}

	//设置光栅化状态,使其生效
	m_deviceContext->RSSetState(m_rasterState);


	// 设置视口,显示全部后缓冲内容
	viewport.Width = (float)screenWidth;
	viewport.Height = (float)screenHeight;
	viewport.MinDepth = 0.0f;
	viewport.MaxDepth = 1.0f;
	viewport.TopLeftX = 0.0f;
	viewport.TopLeftY = 0.0f;

	// 创建视口
	m_deviceContext->RSSetViewports(1, &viewport);

	// 设置透视投影矩阵
	fieldOfView = (float)D3DX_PI / 4.0f;
	screenAspect = (float)screenWidth / (float)screenHeight;

	// 创建透视投影矩阵.
	D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);

	//初始化world矩阵为单位矩阵.
	//该矩阵实现局部坐标到世界坐标的转换
	D3DXMatrixIdentity(&m_worldMatrix);


	// 创建正交投影矩阵,主要用来实施2D渲染.
	D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);

	return true;


}



DirectX11 学习笔记4 - 一个完整的封装框架