Direct3D11程序框架搭建

 

简述
以简单直观的方式搭建Direct3D11程序框架,其中包含了顶点缓存,索引缓存,顶点着色器,像素着色器,变换矩阵等基本的功能,在此基础上学习Direct3D11和HLSL。


简要流程
程序主实现了窗口的创建,D3D中设备,缓存等一些东西的初始化,并在事件循环中进行渲染,渲染结束后释放资源。程序以C语言风格编写,总共有6个函数,六大步骤。
(1)Windows窗口的创建,程序入口函数

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
(2)初始化D3D

bool InitD3DDevice(int screenWidth, int screenHeight, HWND hWnd);
(3)初始化顶点缓存和索引缓存

bool InitVertexBuffer(ID3D11Device* device);
(4)初始化着色器

bool InitShader(ID3D11Device*device, HWND hwnd);
(5)渲染

void Render();
(6)资源释放

void Release();


如图所示


源码

main.cpp

#include < windows.h>
#include < stdlib.h>
#include <dxgi.h>

#include <d3dcommon.h>
#include <d3d11.h>
#include <d3dx10math.h>
#include <d3dx11async.h>

//包含D3D静态库
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")

#define WIDTH 800
#define HEIGHT 600

//D3d变量
IDXGISwapChain* g_swapChain;					//交换链对象
ID3D11Device* g_device;							//设备对象
ID3D11DeviceContext* g_deviceContext;			//设备上下文对象

ID3D11RenderTargetView* g_renderTargetView;		//渲染目标视图
ID3D11Texture2D* g_depthStencilBuffer;
ID3D11DepthStencilState* g_depthStencilState;

ID3D11DepthStencilView* g_depthStencilView;		//深度目标视图
ID3D11RasterizerState* g_rasterState;			//渲染状态


//顶点缓存和索引缓存
struct VertexType
{
	D3DXVECTOR3 position;
	D3DXVECTOR4 color;
};

ID3D11Buffer *g_vertexBuffer, *g_indexBuffer;		
int g_vertexCount, g_indexCount;


//着色器
struct MatrixBufferType
{
	D3DXMATRIX world;
	D3DXMATRIX view;
	D3DXMATRIX projection;
};

ID3D11VertexShader* g_vertexShader;		
ID3D11PixelShader* g_pixelShader;		

ID3D11InputLayout* g_layout;
ID3D11Buffer* g_matrixBuffer;			



// 窗口事件回调函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//初始化D3D
bool InitD3DDevice(int screenWidth, int screenHeight, HWND hWnd);
//初始化顶点缓存和索引缓存
bool InitVertexBuffer(ID3D11Device* device);
//初始化着色器
bool InitShader(ID3D11Device*device, HWND hwnd);
//渲染函数
void Render();
//资源释放
void Release();


//入口函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	//设计窗口类
	WNDCLASS wndclass;
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //设置水平竖直重绘
	wndclass.lpfnWndProc = WindowProc;			//指定回调函数
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_CROSS);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = "D3DWindowClass";

	//注册窗口类
	RegisterClass(&wndclass);

	//创建窗口
	HWND hWnd = CreateWindow(
		"D3DWindowClass",			//窗口类的名字
		"D3DWindow",				//窗口标题
		WS_OVERLAPPEDWINDOW,
		0, 0, 800, 600,
		NULL,
		NULL,
		hInstance,					//实例
		NULL);

	//显示更新窗口
	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);

	//初始化D3D设备
	if (!InitD3DDevice(WIDTH, HEIGHT, hWnd))
	{
		return -1;
	}

	//初始化顶点缓存
	if (!InitVertexBuffer(g_device))
	{
		return -1;
	}

	//初始化着色器
	if (!InitShader(g_device, hWnd))
	{
		return -1;
	}

	//消息循环
	MSG msg;
	BOOL message;
	PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
	while (msg.message != WM_QUIT)
	{
		message = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
		if (message)
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Render();
		}
	}

	//D3D资源释放
	Release();
	// 销毁窗口
	DestroyWindow(hWnd);
	hWnd = NULL;
	return 0;
}

//窗口事件回调函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
		break;
	case WM_KEYUP:
		switch (wParam)
		{
		case VK_ESCAPE:
			DestroyWindow(hWnd);
			return 0;
			break;
		}
		break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

//初始化D3D设备
bool InitD3DDevice(int screenWidth, int screenHeight, HWND hWnd)
{


	HRESULT result;
	IDXGIFactory* factory;
	IDXGIAdapter* adapter;
	IDXGIOutput* adapterOutput;
	unsigned int numModes, i, numerator, denominator, 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;




	// 创建一个DirectX graphics interface factory.
	result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory);
	if (FAILED(result))
	{
		return false;
	}

	// 用接口工厂创建一个主显卡的适配
	result = factory->EnumAdapters(0, &adapter);
	if (FAILED(result))
	{
		return false;
	}

	// 得到主适配器的输出.
	result = adapter->EnumOutputs(0, &adapterOutput);
	if (FAILED(result))
	{
		return false;
	}

	//得到适合 DXGI_FORMAT_R8G8B8A8_UNORM 的显示模式.
	result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL);
	if (FAILED(result))
	{
		return false;
	}

	displayModeList = new DXGI_MODE_DESC[numModes];
	if (!displayModeList)
	{
		return false;
	}

	// 保存显示模式到displayModeList中
	result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);
	if (FAILED(result))
	{
		return false;
	}

	//遍历所有显示模式,得到刷新率两个参数值numerator 和 denominato
	for (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;
			}
		}
	}



	// 释放显示模式列表
	delete[] displayModeList;
	displayModeList = 0;

	//释放适配器输出.
	adapterOutput->Release();
	adapterOutput = 0;

	//释放适配器
	adapter->Release();
	adapter = 0;

	// 释放接口工厂.
	factory->Release();
	factory = 0;

	// 初始化交换链描述
	ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

	// 用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是固定的

	swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator;
	swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator;


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

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

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

	// 设置全屏或者窗口模式.
	swapChainDesc.Windowed = true;


	// 设定扫描线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_11_0;

	// 创建交换链,设备以及设备上下文.
	result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1,
		D3D11_SDK_VERSION, &swapChainDesc, &g_swapChain, &g_device, NULL, &g_deviceContext);
	if (FAILED(result))
	{
		return false;
	}

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

	// 用后缓冲创建渲染目标视图.
	result = g_device->CreateRenderTargetView(backBufferPtr, NULL, &g_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 = g_device->CreateTexture2D(&depthBufferDesc, NULL, &g_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 = g_device->CreateDepthStencilState(&depthStencilDesc, &g_depthStencilState);
	if (FAILED(result))
	{
		return false;

	}

	// 设置深度模版状态.
	g_deviceContext->OMSetDepthStencilState(g_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 = g_device->CreateDepthStencilView(g_depthStencilBuffer, &depthStencilViewDesc, &g_depthStencilView);
	if (FAILED(result))
	{
		return false;
	}

	// 绑定渲染目标视图和深度缓冲到渲染管线.
	g_deviceContext->OMSetRenderTargets(1, &g_renderTargetView, g_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 = g_device->CreateRasterizerState(&rasterDesc, &g_rasterState);
	if (FAILED(result))
	{
		return false;
	}

	//设置光栅化状态,使其生效
	g_deviceContext->RSSetState(g_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;

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

	
	return true;
}

//初始化顶点缓存
bool InitVertexBuffer(ID3D11Device* device)
{
	//创建两个临时数组来保存顶点和索引数据
	VertexType* vertices;			//顶点缓存
	unsigned long* indices;			//索引缓存

	//描述要创建的缓冲区
	D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
	//为缓冲区指定初始化数据
	D3D11_SUBRESOURCE_DATA vertexData, indexData;

	HRESULT result;


	//设置顶点数
	g_vertexCount = 3;

	//设置索引数
	g_indexCount = 3;

	//创建顶点数组
	vertices = new VertexType[g_vertexCount];
	if (!vertices)
	{
		return false;
	}

	//创建缓存数组
	indices = new unsigned long[g_indexCount];
	if (!indices)
	{
		return false;
	}

	//给顶点数组赋值
	vertices[0].position = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
	vertices[0].color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

	vertices[1].position = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	vertices[1].color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

	vertices[2].position = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
	vertices[2].color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

	//给缓存数组赋值
	indices[0] = 0;
	indices[1] = 1;
	indices[2] = 2;


	//设置静态顶点缓冲的描述。
	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(VertexType)* g_vertexCount;  //缓存大小
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;
	vertexBufferDesc.StructureByteStride = 0;
	//缓存区数据
	vertexData.pSysMem = vertices;
	vertexData.SysMemPitch = 0;
	vertexData.SysMemSlicePitch = 0;
	//用设备创建顶点缓存
	result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &g_vertexBuffer);
	if (FAILED(result))
	{
		return false;
	}


	//设置静态索引缓冲区的描述。
	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(unsigned long)* g_indexCount;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;
	indexBufferDesc.StructureByteStride = 0;
	//数据
	indexData.pSysMem = indices;
	indexData.SysMemPitch = 0;
	indexData.SysMemSlicePitch = 0;
	//用设备创建索引缓存
	result = device->CreateBuffer(&indexBufferDesc, &indexData, &g_indexBuffer);
	if (FAILED(result))
	{
		return false;
	}

	//在缓存区创建完成后释放内存
	delete[] vertices;
	vertices = 0;
	delete[] indices;
	indices = 0;

	return true;
}

//初始化着色器
bool InitShader(ID3D11Device*device, HWND hwnd)
{
	WCHAR* vsFileName = (WCHAR*)"./shader/Shader.vs";
	WCHAR* psFileName = (WCHAR*)"./shader/Shader.ps";

	HRESULT result;

	//缓存区
	ID3D10Blob* errorMessage;
	ID3D10Blob* vertexShaderBuffer;
	ID3D10Blob* pixelShaderBuffer;

	D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
	unsigned int numElements;
	D3D11_BUFFER_DESC matrixBufferDesc;


	//初始化为空
	errorMessage = 0;
	vertexShaderBuffer = 0;
	pixelShaderBuffer = 0;

	//编译顶点着色器缓存区
	result = D3DX11CompileFromFile((LPCSTR)vsFileName, NULL, NULL, "ColorVertexShader",
		"vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL,
		&vertexShaderBuffer, &errorMessage, NULL);

	if (FAILED(result))
	{
		return false;
	}

	//编译像素着色器缓存区
	result = D3DX11CompileFromFile((LPCSTR)psFileName, NULL, NULL, "ColorPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL,
		&pixelShaderBuffer, &errorMessage, NULL);
	if (FAILED(result))
	{
		return false;
	}

	//一旦顶点着色和像素着色代码成功地编译成缓冲区,我们就会使用这些缓冲区来创建着色器对象本身。
	//从缓冲区创建顶点着色器。
	result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &g_vertexShader);
	if (FAILED(result))
	{
		return false;
	}

	//从缓冲区创建像素着色器对象
	result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &g_pixelShader);
	if (FAILED(result))
	{
		return false;
	}

	//现在设置进入着色器的数据的布局。
	//这个设置需要与ModelClass和着色器中的VertexType结构相匹配。
	polygonLayout[0].SemanticName = "POSITION";
	polygonLayout[0].SemanticIndex = 0;
	polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
	polygonLayout[0].InputSlot = 0;
	polygonLayout[0].AlignedByteOffset = 0;
	polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[0].InstanceDataStepRate = 0;


	polygonLayout[1].SemanticName = "COLOR";
	polygonLayout[1].SemanticIndex = 0;
	polygonLayout[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	polygonLayout[1].InputSlot = 0;
	polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[1].InstanceDataStepRate = 0;


	//在布局中获取元素的计数
	numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

	//创建顶点输入布局
	result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(),
		vertexShaderBuffer->GetBufferSize(), &g_layout);
	if (FAILED(result))
	{
		return false;
	}

	//释放顶点着色缓冲区和像素着色缓冲区
	vertexShaderBuffer->Release();
	vertexShaderBuffer = 0;
	pixelShaderBuffer->Release();
	pixelShaderBuffer = 0;


	//设置在顶点着色器中动态矩阵常量缓冲区的描述。
	matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
	matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
	matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	matrixBufferDesc.MiscFlags = 0;
	matrixBufferDesc.StructureByteStride = 0;

	//创建恒定的缓冲指针,这样我们就可以从这个类中访问顶点着色常数缓冲区。
	result = device->CreateBuffer(&matrixBufferDesc, NULL, &g_matrixBuffer);
	if (FAILED(result))
	{
		return false;
	}


	return true;
}

//渲染
void Render()
{
	bool result;

	//开始绘制
	float color[4] = { 0.3f, 0.0f, 0.0f, 1.0f };
	//清除后缓冲.
	g_deviceContext->ClearRenderTargetView(g_renderTargetView, color);
	//清除深度缓冲.
	g_deviceContext->ClearDepthStencilView(g_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);


	//设置变换矩阵
	D3DXMATRIX viewMatrix, projectionMatrix, worldMatrix;
	//模型矩阵
	D3DXMatrixIdentity(&worldMatrix);
	//视图矩阵
	D3DXMatrixLookAtLH(&viewMatrix, &D3DXVECTOR3(0.0f, 0.0f, -4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
	//投影矩阵
	D3DXMatrixPerspectiveFovLH(&projectionMatrix, 45, (float)WIDTH / (float)HEIGHT, 1000, 0.1);




	//将模型顶点和索引缓冲区放置在图形管道上,以便为绘图做好准备。
	unsigned int stride;
	unsigned int offset;
	//设置顶点缓冲步和偏移。
	stride = sizeof(VertexType);
	offset = 0;

	//在输入汇编器中设置顶点缓冲,使其能够呈现。
	g_deviceContext->IASetVertexBuffers(0, 1, &g_vertexBuffer, &stride, &offset);
	//将索引缓冲区设置为在输入汇编程序中活动,这样就可以呈现它。
	g_deviceContext->IASetIndexBuffer(g_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
	//设置应该从这个顶点缓冲中呈现的原语类型,在本例中为三角形。
	g_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);



	//设置着色器参数
	D3D11_MAPPED_SUBRESOURCE mappedResource;
	MatrixBufferType* dataPtr;
	unsigned int bufferNumber;

	//在将矩阵发送到着色器之前,请确保转置矩阵,这是DirectX 11的要求,转置矩阵来为着色器做好准备。
	D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
	D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
	D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
	//锁定m矩阵缓冲区,将新的矩阵设置在里面,然后解锁它。
	// 锁定恒定的缓冲区,这样它就可以被写入。
	result = g_deviceContext->Map(g_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
	if (FAILED(result))
	{
		return;
	}

	dataPtr = (MatrixBufferType*)mappedResource.pData;

	dataPtr->world = worldMatrix;
	dataPtr->view = viewMatrix;
	dataPtr->projection = projectionMatrix;

	g_deviceContext->Unmap(g_matrixBuffer, 0);
	bufferNumber = 0;

	g_deviceContext->VSSetConstantBuffers(bufferNumber, 1, &g_matrixBuffer);



	//现在用着色器渲染准备好的缓冲区。
	g_deviceContext->IASetInputLayout(g_layout);
	g_deviceContext->VSSetShader(g_vertexShader, NULL, 0);
	g_deviceContext->PSSetShader(g_pixelShader, NULL, 0);
	g_deviceContext->DrawIndexed(g_indexCount, 0, 0);


	// 锁定屏幕
	g_swapChain->Present(1, 0);

}

//资源释放
void Release()
{
	//释放着色器相关
	if (g_matrixBuffer)
	{	
		g_matrixBuffer->Release();
		g_matrixBuffer = 0;
	}	
	if (g_layout)
	{	
		g_layout->Release();
		g_layout = 0;
	}	
	if (g_pixelShader)
	{	
		g_pixelShader->Release();
		g_pixelShader = 0;
	}	
	if (g_vertexShader)
	{	
		g_vertexShader->Release();
		g_vertexShader = 0;
	}

	//释放索引缓冲区和顶点缓存
	if (g_indexBuffer)
	{
		g_indexBuffer->Release();
		g_indexBuffer = 0;
	}
	if (g_vertexBuffer)
	{
		g_vertexBuffer->Release();
		g_vertexBuffer = 0;
	}


	//释放D3D相关
	if (g_swapChain)
	{	
		g_swapChain->SetFullscreenState(false, NULL);
	}	
	if (g_rasterState)
	{	
		g_rasterState->Release();
		g_rasterState = 0;
	}	
	if (g_depthStencilView)
	{	
		g_depthStencilView->Release();
		g_depthStencilView = 0;
	}	
	if (g_depthStencilState)
	{	
		g_depthStencilState->Release();
		g_depthStencilState = 0;
	}	
	if (g_depthStencilBuffer)
	{	
		g_depthStencilBuffer->Release();
		g_depthStencilBuffer = 0;
	}	
	if (g_renderTargetView)
	{	
		g_renderTargetView->Release();
		g_renderTargetView = 0;
	}	
	if (g_deviceContext)
	{	
		g_deviceContext->Release();
		g_deviceContext = 0;
	}	
	if (g_device)
	{	
		g_device->Release();
		g_device = 0;
	}	
		
	if (g_swapChain)
	{	
		g_swapChain->Release();
		g_swapChain = 0;
	}

}Shader.ps";

	HRESULT result;

	//缓存区
	ID3D10Blob* errorMessage;
	ID3D10Blob* vertexShaderBuffer;
	ID3D10Blob* pixelShaderBuffer;

	D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
	unsigned int numElements;
	D3D11_BUFFER_DESC matrixBufferDesc;


	//初始化为空
	errorMessage = 0;
	vertexShaderBuffer = 0;
	pixelShaderBuffer = 0;

	//编译顶点着色器缓存区
	result = D3DX11CompileFromFile((LPCSTR)vsFileName, NULL, NULL, "ColorVertexShader",
		"vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL,
		&vertexShaderBuffer, &errorMessage, NULL);

	if (FAILED(result))
	{
		return false;
	}

	//编译像素着色器缓存区
	result = D3DX11CompileFromFile((LPCSTR)psFileName, NULL, NULL, "ColorPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL,
		&pixelShaderBuffer, &errorMessage, NULL);
	if (FAILED(result))
	{
		return false;
	}

	//一旦顶点着色和像素着色代码成功地编译成缓冲区,我们就会使用这些缓冲区来创建着色器对象本身。
	//从缓冲区创建顶点着色器。
	result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &g_vertexShader);
	if (FAILED(result))
	{
		return false;
	}

	//从缓冲区创建像素着色器对象
	result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &g_pixelShader);
	if (FAILED(result))
	{
		return false;
	}

	//现在设置进入着色器的数据的布局。
	//这个设置需要与ModelClass和着色器中的VertexType结构相匹配。
	polygonLayout[0].SemanticName = "POSITION";
	polygonLayout[0].SemanticIndex = 0;
	polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
	polygonLayout[0].InputSlot = 0;
	polygonLayout[0].AlignedByteOffset = 0;
	polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[0].InstanceDataStepRate = 0;


	polygonLayout[1].SemanticName = "COLOR";
	polygonLayout[1].SemanticIndex = 0;
	polygonLayout[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	polygonLayout[1].InputSlot = 0;
	polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[1].InstanceDataStepRate = 0;


	//在布局中获取元素的计数
	numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

	//创建顶点输入布局
	result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(),
		vertexShaderBuffer->GetBufferSize(), &g_layout);
	if (FAILED(result))
	{
		return false;
	}

	//释放顶点着色缓冲区和像素着色缓冲区
	vertexShaderBuffer->Release();
	vertexShaderBuffer = 0;
	pixelShaderBuffer->Release();
	pixelShaderBuffer = 0;


	//设置在顶点着色器中动态矩阵常量缓冲区的描述。
	matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
	matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
	matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	matrixBufferDesc.MiscFlags = 0;
	matrixBufferDesc.StructureByteStride = 0;

	//创建恒定的缓冲指针,这样我们就可以从这个类中访问顶点着色常数缓冲区。
	result = device->CreateBuffer(&matrixBufferDesc, NULL, &g_matrixBuffer);
	if (FAILED(result))
	{
		return false;
	}


	return true;
}

//渲染
void Render()
{
	bool result;

	//开始绘制
	float color[4] = { 0.3f, 0.0f, 0.0f, 1.0f };
	//清除后缓冲.
	g_deviceContext->ClearRenderTargetView(g_renderTargetView, color);
	//清除深度缓冲.
	g_deviceContext->ClearDepthStencilView(g_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);


	//设置变换矩阵
	D3DXMATRIX viewMatrix, projectionMatrix, worldMatrix;
	//模型矩阵
	D3DXMatrixIdentity(&worldMatrix);
	//视图矩阵
	D3DXMatrixLookAtLH(&viewMatrix, &D3DXVECTOR3(0.0f, 0.0f, -4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
	//投影矩阵
	D3DXMatrixPerspectiveFovLH(&projectionMatrix, 45, (float)WIDTH / (float)HEIGHT, 1000, 0.1);




	//将模型顶点和索引缓冲区放置在图形管道上,以便为绘图做好准备。
	unsigned int stride;
	unsigned int offset;
	//设置顶点缓冲步和偏移。
	stride = sizeof(VertexType);
	offset = 0;

	//在输入汇编器中设置顶点缓冲,使其能够呈现。
	g_deviceContext->IASetVertexBuffers(0, 1, &g_vertexBuffer, &stride, &offset);
	//将索引缓冲区设置为在输入汇编程序中活动,这样就可以呈现它。
	g_deviceContext->IASetIndexBuffer(g_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
	//设置应该从这个顶点缓冲中呈现的原语类型,在本例中为三角形。
	g_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);



	//设置着色器参数
	D3D11_MAPPED_SUBRESOURCE mappedResource;
	MatrixBufferType* dataPtr;
	unsigned int bufferNumber;

	//在将矩阵发送到着色器之前,请确保转置矩阵,这是DirectX 11的要求,转置矩阵来为着色器做好准备。
	D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
	D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
	D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
	//锁定m矩阵缓冲区,将新的矩阵设置在里面,然后解锁它。
	// 锁定恒定的缓冲区,这样它就可以被写入。
	result = g_deviceContext->Map(g_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
	if (FAILED(result))
	{
		return;
	}

	dataPtr = (MatrixBufferType*)mappedResource.pData;

	dataPtr->world = worldMatrix;
	dataPtr->view = viewMatrix;
	dataPtr->projection = projectionMatrix;

	g_deviceContext->Unmap(g_matrixBuffer, 0);
	bufferNumber = 0;

	g_deviceContext->VSSetConstantBuffers(bufferNumber, 1, &g_matrixBuffer);



	//现在用着色器渲染准备好的缓冲区。
	g_deviceContext->IASetInputLayout(g_layout);
	g_deviceContext->VSSetShader(g_vertexShader, NULL, 0);
	g_deviceContext->PSSetShader(g_pixelShader, NULL, 0);
	g_deviceContext->DrawIndexed(g_indexCount, 0, 0);


	// 锁定屏幕
	g_swapChain->Present(1, 0);

}

//资源释放
void Release()
{
	//释放着色器相关
	if (g_matrixBuffer)
	{	
		g_matrixBuffer->Release();
		g_matrixBuffer = 0;
	}	
	if (g_layout)
	{	
		g_layout->Release();
		g_layout = 0;
	}	
	if (g_pixelShader)
	{	
		g_pixelShader->Release();
		g_pixelShader = 0;
	}	
	if (g_vertexShader)
	{	
		g_vertexShader->Release();
		g_vertexShader = 0;
	}

	//释放索引缓冲区和顶点缓存
	if (g_indexBuffer)
	{
		g_indexBuffer->Release();
		g_indexBuffer = 0;
	}
	if (g_vertexBuffer)
	{
		g_vertexBuffer->Release();
		g_vertexBuffer = 0;
	}


	//释放D3D相关
	if (g_swapChain)
	{	
		g_swapChain->SetFullscreenState(false, NULL);
	}	
	if (g_rasterState)
	{	
		g_rasterState->Release();
		g_rasterState = 0;
	}	
	if (g_depthStencilView)
	{	
		g_depthStencilView->Release();
		g_depthStencilView = 0;
	}	
	if (g_depthStencilState)
	{	
		g_depthStencilState->Release();
		g_depthStencilState = 0;
	}	
	if (g_depthStencilBuffer)
	{	
		g_depthStencilBuffer->Release();
		g_depthStencilBuffer = 0;
	}	
	if (g_renderTargetView)
	{	
		g_renderTargetView->Release();
		g_renderTargetView = 0;
	}	
	if (g_deviceContext)
	{	
		g_deviceContext->Release();
		g_deviceContext = 0;
	}	
	if (g_device)
	{	
		g_device->Release();
		g_device = 0;
	}	
		
	if (g_swapChain)
	{	
		g_swapChain->Release();
		g_swapChain = 0;
	}

}


着色器

Shader.vs

//全局变量
cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};


//类型
struct VertexInputType
{
    float4 position : POSITION;
    float4 color : COLOR;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float4 color : COLORS;
};


//顶点着色器入口
PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;
    

    //将位置矢量改变为4个单位
    input.position.w = 1.0f;

    //矩阵变换,模型矩阵*视图矩阵*透视矩阵
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
    //存储用于像素着色器的输入颜色。
    output.color = input.position;
    
    return output;
}

 

 

 

 

Shader.ps

struct PixelInputType
{
    float4 position : SV_POSITION;
    float4 color : COLORS;
};


float4 ColorPixelShader(PixelInputType input) : SV_TARGET
{
    return input.color;
}

 

结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值