简述
以简单直观的方式搭建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
#include
#include
#include
#include
//包含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; iRelease();
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;
}
结果