天天看點

D3D11 渲染狀态

這兒是在上一個部落格基礎上修改轉換代碼。在D3D中,物體都是停留在目前狀态中的,沒有物體會回退到它的“預設”狀态。比如圖元拓撲,一旦設定了它,就像之前在一個三角形清單中所做的一樣,除非顯式的去改變它,否則它就會一直停留在三角形清單中。就像頂點和索引緩沖,一旦将它們綁定到管線,除非去改變它們,否則它們就會一直停留在那兒。這兒,将說到的是渲染狀态。渲染狀态所做的就是封裝能夠用來配置d3d的設定。有不同狀态供我們選擇:

ID3D11RasterizerState

該接口用于客制化管線的光栅化階段,本部落格中将會用到它

ID3D11BlendState

這用于混合階段。

ID3D11DepthStencilState

該狀态接口用于配置深度模闆測試。在之後會說到模闆緩沖,且深度緩沖設定用來做預設的深度測試。

全局聲明

這是一個接口對象的聲明,用于設定RS管線階段的渲染狀态。

ID3D11RasterizerState* WireFrame;
           

銷毀

别忘記

void CleanUp()
{
    //Release the COM Objects we created
    SwapChain->Release();
    d3d11Device->Release();
    d3d11DevCon->Release();
    renderTargetView->Release();
    squareVertBuffer->Release();
    squareIndexBuffer->Release();
    VS->Release();
    PS->Release();
    VS_Buffer->Release();
    PS_Buffer->Release();
    vertLayout->Release();
    depthStencilView->Release();
    depthStencilBuffer->Release();
    cbPerObjectBuffer->Release();
    ///**************new**************
    WireFrame->Release();
    ///**************new**************
}
           

描述渲染狀态

D3D11_RASTERIZER_DESC

通過描述一個聲明為D3D11_RASTERIZER_DESC結構體的wfdesc變量開始。在該變量中會要建立的存儲光栅化狀态的定義:

typedef struct D3D11_RASTERIZER_DESC {
  D3D11_FILL_MODE FillMode;
  D3D11_CULL_MODE CullMode;
  BOOL            FrontCounterClockwise;
  INT             DepthBias;
  FLOAT           DepthBiasClamp;
  FLOAT           SlopeScaledDepthBias;
  BOOL            DepthClipEnable;
  BOOL            ScissorEnable;
  BOOL            MultisampleEnable;
  BOOL            AntialiasedLineEnable;
} D3D11_RASTERIZER_DESC;
           

FillMode

在這兒能設定兩種模式:線框渲染的D3D11_FILL_WIREFRAME模式,或者實體渲染的D3D11_FILL_SOLID模式,通常都是這種模式,它是預設模式。

CullMode

可以設定D3D11_CULL_NONE來禁止裁剪(也就是不渲染三角形的另外一邊),D3D11_CULL_FRONT用于裁剪前面部分(這時前面不會被渲染),D3D11_CULL_BACK用于裁剪後面部分(這時後面不會被渲染),這也是預設的模式。

FrontCounterClockwise

将這設為true或false。true意味着如果三角形頂點以順時針繞着相機渲染,那麼就是前面,false則是相反的。

DepthBias

将深度值添加到一個給定像素。預設值是0.0f

DepthBiasClamp

指定一個像素的最大深度偏差。預設值是0.0f

SlopeScaledDepthBias

指定給定像素斜率上的标量。預設值是0.0f

DepthClipEnable

基于離相機的距離來使能或禁止剪裁

ScissorEnable

使能或禁止矩形剪刀剪裁。所有的位于激活剪刀矩形外的像素會被裁剪掉。預設值是FALSE。

MultiSampleEnable

使能或禁止多重采樣抗鋸齒

AntialiasedLineEnable

使能或禁止線性抗鋸齒。注意該選項隻在α混合使能時或繪制線條時或MultisampleEnable成員為FALSE時應用。該預設值為FALSE。

D3D11_RASTERIZER_DESC wfdesc;
           

填充D3D11_RASTERIZER_DESC結構體

首先確定記憶體是清空的。随後設定filllmode為D3D11_FILL_WIREFRAME,是以d3d以線框方式渲染立方體。随後設定cullmode為D3D_CULL_NONE,是以當旋轉時能夠看到立方體的背面。

在填充完D3D11_RASTERIZER_DESC結構體之後,需要建立新的渲染狀态。渲染狀态将會被綁定到管線的RS階段,使用函數ID3D11Device::CreateRasterizerState()方法建立渲染狀态。第一個參數是渲染狀态的描述符,第二個參數是一個指向ID3D11RasterizerState對象的指針,它将會存儲新的渲染狀态。

ZeroMemory(&wfdesc, sizeof(D3D11_RASTERIZER_DESC));
wfdesc.FillMode = D3D11_FILL_WIREFRAME;
wfdesc.CullMode = D3D11_CULL_NONE;
hr = d3d11Device->CreateRasterizerState(&wfdesc, &WireFrame);
           

設定渲染狀态

在建立完渲染狀态之後,需要設定它,或将它綁定到管線的RS階段。可調用方法ID3D11DeviceContext::RSSetState()來做這件事情。唯一的一個參數就是想要綁定的渲染狀态。

大多數時間,對象會使用場景中不同的渲染狀态,是以當初始化場景時設定的渲染狀态一般都不是所想要的,需要在每個想要用到那個渲染狀态的對象或對象組之前設定渲染狀态。若要使用預設渲染狀态,隻需要傳入一個NULL到該函數即可。

d3d11DevCon->RSSetState(WireFrame);
           

代碼如下:

#include "stdafx.h"
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")

#include <windows.h>
#include "Resource.h"
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>

//全局描述符
IDXGISwapChain* SwapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DevCon;
ID3D11RenderTargetView* renderTargetView;

//索引緩沖
ID3D11Buffer* squareIndexBuffer;
ID3D11Buffer* squareVertBuffer;

//深度值-20170927
ID3D11DepthStencilView* depthStencilView;
ID3D11Texture2D* depthStencilBuffer;

//着色器
ID3D11Buffer* triangleVertBuffer;
ID3D11VertexShader* VS;
ID3D11PixelShader* PS;
ID3D10Blob* VS_Buffer;
ID3D10Blob* PS_Buffer;
ID3D11InputLayout* vertLayout;

///
ID3D11Buffer* cbPerObjectBuffer;
///

// 設定線框
ID3D11RasterizerState* WireFrame;


#if 0
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
int colormodr = 1;
int colormodg = 1;
int colormodb = 1;
#endif
/
LPCTSTR WndClassName = "firstwindow";
HWND hwnd = NULL;
HRESULT hr;

const int Width = 800; //設定寬
const int Height = 800; // 設定高

///四個空間以及相機屬性
XMMATRIX WVP;
//立方體
XMMATRIX cube1World;
XMMATRIX cube2World;
//
XMMATRIX World;
XMMATRIX camView;
XMMATRIX camProjection;

XMVECTOR camPosition;
XMVECTOR camTarget;
XMVECTOR camUp;

//相機
XMMATRIX Rotation;
XMMATRIX Scale;
XMMATRIX Translation;
float rot = 0.01f;

//函數聲明
bool InitializeDirect3d11App(HINSTANCE hInstance);
//void ReleaseObjects();
void CleanUp();
bool InitScene();
void UpdateScene();
void DrawScene();

// 初始化視窗
bool InitializeWindow(HINSTANCE hInstance,
	int ShowWnd,
	int width, int height,
	bool windowed);

//初始化消息循環函數
int messageloop();
//初始化視窗回調過程。Windows API是事件驅動型的程式設計模型。在該函數中捕獲Windows消息,比如一個按鍵按下(也叫事件)以及程式操作流程。

LRESULT CALLBACK WndProc(HWND hWnd,
	UINT msg,
	WPARAM wParam,
	LPARAM lParam);

//建立效果常量緩沖的結構體
struct cbPerObject
{
	XMMATRIX WVP;
};

cbPerObject cbPerObj;

//頂點結構體以及頂點布局(輸入布局)
struct Vertex
{
	Vertex(){}
	Vertex(float x, float y, float z,
		float cr, float cg, float cb, float ca)
		:pos(x, y, z), color(cr, cg, cb, ca){}
	XMFLOAT3 pos;
	XMFLOAT4 color;
};

D3D11_INPUT_ELEMENT_DESC layout[] = {
	{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
	{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);

//主函數,傳入應用程式句柄hInstance,前一個應用程式句柄hPrevInstance,傳給函數處理的指令行lpCmdLine以及視窗顯示方式的nShowCmd
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nShowCmd)
{
	//建立并注冊視窗
	if (!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
	{
		MessageBox(0, "Window Initilization - Failed", "Error", MB_OK);
		return 0;
	}

	/new
	if (!InitializeDirect3d11App(hInstance)) // 初始化D3D
	{
		MessageBox(0, "Direct3D Initialization - Failed", "Error", MB_OK);
		return 0;
	}

	if (!InitScene())
	{
		MessageBox(0, "Scene Initialization - Failed", "Error", MB_OK);
		return 0;
	}
	
	messageloop();
	CleanUp();
	//ReleaseObjects();

	return 0;
}
// windowed 若為true則為視窗模式顯示,若為false則為全屏模式顯示
bool InitializeWindow(HINSTANCE hInstance,
	int ShowWnd,
	int width, int height,
	bool windowed)
{
	/*typedef struct _WNDCLASS{
		UINT cbSize;
		UINT style;
		WNDPROC lpfnWndProc;
		int cbClsExtra;
		int cbWndExtra;
		HANDLE hInstance;
		HICON hIcon;
		HCURSOR hCursor;
		HBRUSH hbrBackground;
		LPCTSTR lpszMenuName;
		LPCTSTR lpszClassName;
	}WNDCLASS;
	*/
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX); //window類的大小
	/********windows類風格
	*CS_CLASSDC 一個使用該類建立的在所有視窗間共享的裝置上下文
	*CS_DBLCLKS 在視窗上使能輕按兩下功能
	*CS_HREDRAW 若視窗的寬度有改變或者視窗水準地移動,視窗将會重新整理
	*CS_NOCLOSE 視窗菜單上禁止關閉選項
	*CS_OWNDC   為每個視窗建立自己的裝置上下文。正好與CS_CLASSDC相反
	*CS_PARENTDC 這會設定建立的子視窗的剪裁四邊形到父視窗,這允許子視窗能夠在父視窗上繪畫
	*CS_VERDRAW 若在視窗的高度或視窗在垂直方向有移動視窗會重繪
	**/
	wc.style = CS_HREDRAW | CS_VREDRAW;
	//lpfnWndProc是一個指向處理視窗消息函數的指針,設定視窗處理函數的函數名WndProc
	wc.lpfnWndProc = WndProc;
	//cbClsExtra是WNDCLASSEX之後額外申請的位元組數
	wc.cbClsExtra = NULL;
	//cbWndExtra指定視窗執行個體之後所申請的位元組數
	wc.cbWndExtra = NULL;
	//目前視窗應用程式的句柄,通過給函數GetModuleHandle()函數第一個參數傳入NULL可擷取目前視窗應用程式。
	wc.hInstance = hInstance;

	//hIcon用來指定視窗标題欄左上角的圖示。以下是一些标準圖示:
	/*
	*IDI_APPLICATION 預設應用程式圖示
	*IDI_HAND 手形狀的圖示
	*IDI_EXCLAMATION 感歎号圖示
	*IDI_INFORMATION 星号圖示
	*IDI_QUESTION 問号圖示
	*IDI_WINLOGO 若使用的是XP則是預設應用程式圖示,否則是視窗logo
	*/
	wc.hIcon = LoadIcon(NULL, (LPCTSTR)IDI_SMALL);

	/*定義光标圖示
	*IDC_APPSTARTING 标準箭頭以及小型沙漏光标
	*IDC_ARROW 标準箭頭光标
	*IDC_CROSS 十字線光标
	*IDC_HAND 手型光标
	*IDC_NO 斜線圈光标
	*IDC_WAIT 沙漏光标
	*/
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	//hbrBackground是一個刷子的句柄,可使得背景黑色。
	wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW + 2);
	//附加到視窗的菜單名字,不需要的話設定為NULL
	wc.lpszMenuName = NULL;
	//對類進行命名
	wc.lpszClassName = WndClassName;
	//指定工作列的圖示,使用上面的IDI_圖示
	wc.hIconSm = LoadIcon(NULL, (LPCTSTR)IDI_MYICON);
	//注冊類。若失敗則會獲得一個錯誤,若成功,則繼續建立視窗
	if (!RegisterClassEx(&wc))
	{
		MessageBox(NULL, "Error registering class", "Error", MB_OK | MB_ICONERROR);
		return 1;
	}

	//建立視窗
	hwnd = CreateWindowEx(NULL, WndClassName, "Rotating Cube", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width,
		height, NULL, NULL, hInstance, NULL);

	if (!hwnd)
	{
		MessageBox(NULL, "Error registering class", "Error", MB_OK | MB_ICONERROR);
		return 1;
	}

	//BOOL ShowWindow(HWND hWnd, int nCmdShow);
	//BOOL UpdateWindow(HWND hWnd);

	ShowWindow(hwnd, ShowWnd);
	UpdateWindow(hwnd);// 發送WM_PAINT消息到視窗過程,若視窗客戶區沒有任何東西要顯示,則不發送消息。傳回true,繼續運作到mainloop中去。

	return true;
}

bool InitializeDirect3d11App(HINSTANCE hInstance)
{
	//聲明緩沖
	DXGI_MODE_DESC bufferDesc;

	ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));

	bufferDesc.Width = Width;
	bufferDesc.Height = Height;
	bufferDesc.RefreshRate.Numerator = 60;
	bufferDesc.RefreshRate.Denominator = 1;
	bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

	//聲明交換鍊
	DXGI_SWAP_CHAIN_DESC swapChainDesc;

	ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));

	swapChainDesc.BufferDesc = bufferDesc;
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.BufferCount = 1;
	swapChainDesc.OutputWindow = hwnd;
	swapChainDesc.Windowed = TRUE;
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;


	//建立交換鍊
	D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
		D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);

	//建立後緩沖
	ID3D11Texture2D* BackBuffer;
	SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&BackBuffer);

	//建立渲染目标
	d3d11Device->CreateRenderTargetView(BackBuffer, NULL, &renderTargetView);
	BackBuffer->Release();

	//建立深度模闆緩沖
	D3D11_TEXTURE2D_DESC depthStencilDesc;
	depthStencilDesc.Width = Width;
	depthStencilDesc.Height = Height;
	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; //綁定到OM
	depthStencilDesc.CPUAccessFlags = 0;
	depthStencilDesc.MiscFlags = 0;

	//建立深度模闆視圖
	d3d11Device->CreateTexture2D(&depthStencilDesc, NULL, &depthStencilBuffer);
	d3d11Device->CreateDepthStencilView(depthStencilBuffer, NULL, &depthStencilView);

	//設定渲染目标
	d3d11DevCon->OMSetRenderTargets(1, &renderTargetView, depthStencilView);

	return true;
}

void CleanUp()
{
	SwapChain->Release();
	d3d11Device->Release();
	d3d11DevCon->Release();
	renderTargetView->Release();

	squareVertBuffer->Release();
	squareIndexBuffer->Release();

	//triangleVertBuffer->Release();
	VS->Release();
	PS->Release();
	VS_Buffer->Release();
	PS_Buffer->Release();
	vertLayout->Release();

	depthStencilView->Release();
	depthStencilBuffer->Release();

	//
	cbPerObjectBuffer->Release();

	//釋放線框
	WireFrame->Release();
}

void ReleaseObjects()
{
//釋放建立的COM對象
	SwapChain->Release();
	d3d11Device->Release();
	d3d11DevCon->Release();
}

bool InitScene()
{
	//編譯着色器
	hr = D3DX11CompileFromFile("Effects.fx", 0, 0, "VS", "vs_4_0", 0, 0, 0, &VS_Buffer, 0, 0);
	hr = D3DX11CompileFromFile("Effects.fx", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS_Buffer, 0, 0);

	//建立着色器對象
	hr = d3d11Device->CreateVertexShader(VS_Buffer->GetBufferPointer(), VS_Buffer->GetBufferSize(), NULL, &VS);
	hr = d3d11Device->CreatePixelShader(PS_Buffer->GetBufferPointer(), PS_Buffer->GetBufferSize(), NULL, &PS);

	//設定頂點和像素着色器
	d3d11DevCon->VSSetShader(VS, 0, 0);
	d3d11DevCon->PSSetShader(PS, 0, 0);

	//建立頂點緩沖
	Vertex v[] = {
		Vertex(-1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f),
		Vertex(-1.0f, +1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f),
		Vertex(+1.0f, +1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f),
		Vertex(+1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f),
		Vertex(-1.0f, -1.0f, +1.0f, 0.0f, 1.0f, 1.0f, 1.0f),
		Vertex(-1.0f, +1.0f, +1.0f, 1.0f, 1.0f, 1.0f, 1.0f),
		Vertex(+1.0f, +1.0f, +1.0f, 1.0f, 0.0f, 1.0f, 1.0f),
		Vertex(+1.0f, -1.0f, +1.0f, 1.0f, 0.0f, 0.0f, 1.0f),
	};

	DWORD indices[] = {
		// front face
		0, 1, 2,
		0, 2, 3,

		// back face
		4, 6, 5,
		4, 7, 6,

		// left face
		4, 5, 1,
		4, 1, 0,

		// right face
		3, 2, 6,
		3, 6, 7,

		// top face
		1, 5, 6,
		1, 6, 2,

		// bottom face
		4, 0, 3,
		4, 3, 7
	};

	D3D11_BUFFER_DESC indexBufferDesc;
	ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));

	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(DWORD) * 12 * 3;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA iinitData;
	iinitData.pSysMem = indices;
	d3d11Device->CreateBuffer(&indexBufferDesc, &iinitData, &squareIndexBuffer);
	d3d11DevCon->IASetIndexBuffer(squareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

	D3D11_BUFFER_DESC vertexBufferDesc;
	ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));

	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(Vertex) * 8;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA vertexBufferData;
	ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
	vertexBufferData.pSysMem = v;
	hr = d3d11Device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &squareVertBuffer);

	//設定頂點緩沖
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	d3d11DevCon->IASetVertexBuffers(0, 1, &squareVertBuffer, &stride, &offset);

	//建立輸入布局
	d3d11Device->CreateInputLayout(layout, numElements, VS_Buffer->GetBufferPointer(),
		VS_Buffer->GetBufferSize(), &vertLayout);

	//設定輸入布局
	d3d11DevCon->IASetInputLayout(vertLayout);
	
	//設定圖元拓撲
	d3d11DevCon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	//建立視口
	D3D11_VIEWPORT viewport;
	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

	viewport.TopLeftX = 0;
	viewport.TopLeftY = 0;
	viewport.Width = Width;
	viewport.Height = Height;
	
	viewport.MinDepth = 0;
	viewport.MaxDepth = 1;
	//設定視口
	d3d11DevCon->RSSetViewports(1, &viewport);

	//建立緩沖用來發送到效果檔案的cbuffer
	D3D11_BUFFER_DESC cbbd;
	ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));
	cbbd.Usage = D3D11_USAGE_DEFAULT;
	cbbd.ByteWidth = sizeof(cbPerObject);
	cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	cbbd.CPUAccessFlags = 0;
	cbbd.MiscFlags = 0;

	hr = d3d11Device->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);

	//相機資訊
	//相機資訊
	camPosition = XMVectorSet(0.0f, 3.0f, -8.0f, 0.0f);
	//camPosition = XMVectorSet(0.0f, 0.0f, -0.5f, 0.0f);
	camTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
	camUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

	//設定視圖矩陣
	camView = XMMatrixLookAtLH(camPosition, camTarget, camUp);

	//設定投影矩陣
	camProjection = XMMatrixPerspectiveFovLH(0.4f*3.14f, (float)Width / Height, 1.0f, 1000.0f);

	//設定線框
	D3D11_RASTERIZER_DESC wfdesc;
	ZeroMemory(&wfdesc, sizeof(D3D11_RASTERIZER_DESC));
	wfdesc.FillMode = D3D11_FILL_WIREFRAME;
	wfdesc.CullMode = D3D11_CULL_NONE;
	hr = d3d11Device->CreateRasterizerState(&wfdesc, &WireFrame);
	d3d11DevCon->RSSetState(WireFrame);

	return true;
}

void UpdateScene()
{
	// 更新場景顔色
	//讓立方體旋轉起來
	rot += 0.00005f;
	if (rot > 6.26f)
		rot = 0.0f;

	//複位cube1World
	cube1World = XMMatrixIdentity();

	//定義cube1的世界空間矩陣
	XMVECTOR rotaxis = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	Rotation = XMMatrixRotationAxis(rotaxis, rot);
	Translation = XMMatrixTranslation(0.0f, 0.0f, 4.0f);

	//用轉換設定cube1的世界空間
	cube1World = Translation* Rotation;

	//複位cube2World
	cube2World = XMMatrixIdentity();
	
	//定義cube2的世界空間矩陣
	Rotation = XMMatrixRotationAxis(rotaxis, -rot);
	Scale = XMMatrixScaling(1.3f, 1.3f, 1.3f);

	//設定cube2的世界空間矩陣
	cube2World = Rotation * Scale;

#if 0
	red += colormodr * 0.00005f;
	green += colormodg * 0.00002f;
	blue += colormodb * 0.00001f;

	if (red >= 1.0f || red <= 0.0f)
		colormodr *= -1;
	if (green >= 1.0f || green <= 0.0f)
		colormodg *= -1;
	if (blue >= 1.0f || blue <= 0.0f)
		colormodb *= -1;
#endif
}

void DrawScene()
{
	//将更新的顔色填充後緩沖
//	D3DXCOLOR bgColor(red, green, blue, 1.0f);
	float bgColor[4] = {(0.0f, 0.0f, 0.0f, 0.0f)};
	d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);

	//重新整理深度模闆視圖
	d3d11DevCon->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

	//設定WVP矩陣并将它送到效果檔案中的常量緩沖中
	WVP = cube1World * camView * camProjection;
	cbPerObj.WVP = XMMatrixTranspose(WVP);
	d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);
	d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);

	//繪制第一個立方體
	d3d11DevCon->DrawIndexed(36, 0, 0);

	//設定世界/視圖/投影矩陣,随後發送到效果檔案的常量緩沖中
	//World = XMMatrixIdentity();

	WVP = cube2World * camView * camProjection;
	cbPerObj.WVP = XMMatrixTranspose(WVP);
	d3d11DevCon->UpdateSubresource(cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0);
	d3d11DevCon->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer);

	//繪制第二個立方體
	d3d11DevCon->DrawIndexed(36, 0, 0);
	//繪制三角形
	//d3d11DevCon->DrawIndexed(6, 0, 0);
	//畫三角形
	//d3d11DevCon->Draw(3, 0);

	//将後緩沖呈現到螢幕
	SwapChain->Present(0, 0);
}

int messageloop(){
	MSG msg;
	ZeroMemory(&msg, sizeof(MSG));//清除結構體被設為NULL。

	while (true){
		//使用PeekMessage()檢查是否有消息傳進來
		/*LPMSG lpMsg 消息結構體的指針
		*HWND hWnd 發送消息的視窗句柄。若設為NULL,那麼它會從目前程式中接收來自任何一個視窗的消息
		*UINT wMsgFilterMin 指定消息範圍内第一個要檢查的消息的值。若wMsgFilterMin和wMsgFilterMax都設為0,那麼PeekMessage将會檢查素有的消息
		*UINT wMsgFilterMax 指定消息範圍内最後一個要檢測的消息的值
		*UINT wRemoveMsg 指定消息的處理方式。若設定為PM_REMOVE,則在讀取之後會被删除
		*/
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
			{
				break;
			}
			//若消息為視窗消息,則解析并分發它。TranslateMessage()将會讓視窗做一些解析,類似鍵盤的虛拟鍵值轉換到字元形式。
			//而DispatchMessage()則發送消息到視窗過程WndProc。
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else //若沒有視窗消息,則運作遊戲
		{
			 // run game code
			UpdateScene();
			DrawScene();
		}
	}
	return msg.wParam;
}

//視窗消息處理函數
//HWND hwnd 擷取消息的視窗句柄
//UINT msg 消息的内容
/*
*WM_ACTIVE 當視窗激活時發送的消息
*WM_CLOSE 當視窗關閉時發送的消息
*WM_CREATE 當視窗建立時發送的消息
*WM_DESTROY 當視窗銷毀時發送的消息
*/
//wParam和lParam時消息的額外資訊。使用wParam來檢測鍵盤輸入消息
LRESULT CALLBACK WndProc(HWND hwnd,
	UINT msg,
	WPARAM wParam,
	LPARAM lParam
	)
{
	// 這是事件檢測消息的地方,若escape鍵被按下,會顯示一個消息框,詢問是否真的退出。若點選yes,則程式關閉。若不點選,則消息框關閉。若消息包含WM_DESTROY
	// 則意味着視窗正在被銷毀,傳回0并且程式關閉
	switch (msg)
	{
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
		{
			if (MessageBox(0, "Are you sure you want to exit?",
				"Really?", MB_YESNO | MB_ICONASTERISK) == IDYES)
			{
				DestroyWindow(hwnd);
			}
			return 0;

		}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		break;
	}

	//調用預設視窗過程函數
	return DefWindowProc(hwnd,
		msg,
		wParam,
		lParam);
}
           

效果如下:

D3D11 渲染狀态

參考網址

繼續閱讀