// D3Dtest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//代码来自基于 DirectX11 的 3D 图形程序设计案例教程 重庆大学
#include "d3dinit.h"
#include <d3dCompiler.h>
#define D3DCOMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)
#define D3DCOMPILE_ENABLE_STRICTNESS 0x1
ID3D11Device* device = NULL; //D3D11设备指针
IDXGISwapChain* swapChain = NULL; //交换链指针
ID3D11DeviceContext* immediateContext = NULL; //设备上下文指针
ID3D11RenderTargetView* renderTargetView = NULL;//渲染目标视图指针
//定点和像素(片源着色)器
ID3D11VertexShader* v_shader;
ID3D11PixelShader* p_shader;
struct st_Vertex {
XMFLOAT3 Pos;//顶点结构体
};
//着色器处理
bool SetUp()
{
// 第一步, 创建顶点着色器
// 定义一个着色器编译标识符
// D3DCOMPILE_ENABLE_STRICTINESS 表示强制严格编译
const D3D_SHADER_MACRO defines[] = { NULL };
ID3DBlob* pVSBlob = nullptr;
ID3DBlob* errorBlob = nullptr;
if (FAILED(D3DCompileFromFile(
L"VertexShader.hlsl", // 着色器文件路径
defines, // 宏定义数组(原D3DX11版本未使用)
D3DCOMPILE_STANDARD_FILE_INCLUDE, // 自动处理include文件
"VSMain", // 着色器入口函数
"vs_5_0", // 着色器目标版本
D3DCOMPILE_ENABLE_STRICTNESS, // 编译标志(保留原有逻辑)
0, // 次级标志(Effect编译相关)
&pVSBlob, // 输出字节码
&errorBlob)) // 错误信息
)
{
// 如果编译失败, 弹出一个消息框
MessageBox(NULL, L"Fail to compile vertex shader", L"ERROR", MB_OK);
return S_FALSE;
}
// 用 CreateVertexShader 创建顶点着色器
device->CreateVertexShader(
pVSBlob->GetBufferPointer(), // 指向 pVSBlob 所在内存块的起始地址
pVSBlob->GetBufferSize(), // 取得 pVSBlob 的大小
NULL, // 指向 ID3D11ClassLinkage 的指针, 一般为空
&v_shader); // 将创建好的顶点着色器存放到 vertexShader 中
// 第二步, 创建像素着色器
// 声明一个 ID3DBlob 对象来存放编译后的像素着色器
ID3DBlob* pPSBlob = NULL;
if (FAILED(D3DCompileFromFile(
L"VertexShader.hlsl", // 着色器文件路径
defines, // 宏定义数组(原D3DX11版本未使用)
D3DCOMPILE_STANDARD_FILE_INCLUDE, // 自动处理include文件
"PSMain", // 着色器入口函数
"ps_5_0", // 着色器目标版本
D3DCOMPILE_ENABLE_STRICTNESS, // 编译标志(保留原有逻辑)
0, // 次级标志(Effect编译相关)
&pPSBlob, // 输出字节码
&errorBlob)) // 错误信息
)
{
// 如果编译失败, 弹出一个消息框
MessageBox(NULL, L"Fail to compile vertex shader", L"ERROR", MB_OK);
return S_FALSE;
}
// 用 CreatePixelShader 创建像素着色器
device->CreatePixelShader(
pPSBlob->GetBufferPointer(), // 指向 pPSBlob 所在内存块的起始地址
pPSBlob->GetBufferSize(), // 取得 pPSBlob 的大小
NULL, // 指向 ID3D11ClassLinkage 的指针, 一般为空
&p_shader); // 将创建好的像素着色器存放到 pixelShader 中
// 第三步, 创建并设置输入布局
// 所谓输入布局, 就是制定顶点结构所包含信息的实际意义
// D3D11_INPUT_ELEMENT_DESC 用于描述顶点结构的意义
// 以便让显卡识别所定义的顶点结构
// 这里定义一个 D3D11_INPUT_ELEMENT_DESC 数组,
// 由于定义的顶点结构只有位置坐标, 所有这个数组里也只有一个元素
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{
"POSITION", // 语义标识符, 必须和 hlsl 文件中 VSMain 所用的标识符一致
0, // 表示第 1 个元素, 注意和数组一样都是从 0 开始计数,
DXGI_FORMAT_R32G32B32_FLOAT, // 96 位浮点像素, 红绿蓝各 32 位
0, // 可以取值 0 - 15, 0 表示绑定顶点缓存到第一个输入槽
0, // 可选项, 定义了缓存的对齐方式,
D3D11_INPUT_PER_VERTEX_DATA, // 定义输入数据类型为顶点数据
0 // 本例没有使用实例技术, 所以这里为 0
}
};
// 获取输入布局中元素个数
UINT numElements = ARRAYSIZE(layout);
// 声明一个输入布局对象 pVertexLayout 用于存放创建好的布局
ID3D11InputLayout* pVertexLayout;
// 调用 CreateInputLayout 创建输入布局
device->CreateInputLayout(
layout, // 上面定义的 D3D11_INPUT_ELEMENT_DESC 数组
numElements, // D3D11_INPUT_ElEMENT_DESC 数组的元素个数
pVSBlob->GetBufferPointer(), // 指向顶点着色器起始位置的指针
pVSBlob->GetBufferSize(), // 指向顶点着色器的所在内存大小
&pVertexLayout); // 返回生成的输入布局对象
// 设置生成的输入布局
immediateContext->IASetInputLayout(pVertexLayout);
// 第四步, 创建顶点缓存
// 用我们自己定义的 Vertex 结构创建三角形的三个顶点坐标
st_Vertex vertices[] =
{
XMFLOAT3(0.0f, 0.5f, 0.0f),
XMFLOAT3(0.5f, 0.0f, 0.0f),
XMFLOAT3(-0.5f, -0.5f, 0.0f),
XMFLOAT3(0.5f, 0.5f, 0.0f)
};
// 填充 D3D11_BUFFER_DESC 结构, 这个结构是用来描述顶点缓存的属性
// 首先声明一个 D3D11_BUFFER_DESC 的对象 bd
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd)); // 进行清零操作
bd.Usage = D3D11_USAGE_DEFAULT; // 设置缓存的读写方式, 一般用默认方式
bd.ByteWidth = sizeof(st_Vertex) * 3; // 设置缓存区域的大小,
// 由于有三个顶点所以要乘以 3
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 将这个缓存区域绑定到顶点缓存
bd.CPUAccessFlags = 0; // CPU 访问标识符, 0 表示没有 CPU 访问
bd.MiscFlags = 0; // 其他项标识符, 0 表示不使用该项
// 声明一个数据用于初始化子资源
D3D11_SUBRESOURCE_DATA initData;
ZeroMemory(&initData, sizeof(initData)); // 进行清零操作
initData.pSysMem = vertices; // 设置需要初始化的数据, 即顶点数组
// 声明一个 ID3D11Buffer 对象作为顶点缓存
ID3D11Buffer* vertexBuffer;
// 调用 CreateBuffer 创建顶点
device->CreateBuffer(&bd, &initData, &vertexBuffer);
UINT stride = sizeof(st_Vertex); // 获取 Vertex 的大小作为跨度
UINT offset = 0; // 设置偏移量为 0
// 设置顶点缓存
immediateContext->IASetVertexBuffers(
0, // 绑定到第一个输入槽
1, // 顶点缓存的个数, 这里为一个
&vertexBuffer, // 创建好的顶点缓存
&stride, // 跨度, 即顶点结构的大小
&offset); // 缓存第一个元素到所用元素的偏移量
// 指定图元类型, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST 表示图元为三角形
immediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
return true;
}
void Cleanup()
{
//释放指针
if (renderTargetView) renderTargetView->Release();
if (immediateContext) immediateContext->Release();
if (swapChain) swapChain->Release();
if (device) device->Release();
if (v_shader) v_shader->Release();
if (p_shader) p_shader->Release();
}
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//处理窗口消息
switch (msg)
{
case WM_DESTROY:
::PostQuitMessage(0);
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
::DestroyWindow(hwnd);
break;
}
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
bool Display(float timeDelta)
{
if (device)
{
// 声明一个数组存放颜色信息, 4 个元素分别表示红, 绿, 蓝以及 alpha
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f };
// 清除渲染目标视图
immediateContext->ClearRenderTargetView(renderTargetView,
ClearColor);
// 把创建好的顶点着色器和像素着色器绑定到 immediateContext
immediateContext->VSSetShader(v_shader, NULL, 0);
immediateContext->PSSetShader(p_shader, NULL, 0);
// 绘制三角形, 第一个参数表示绘制 3 个点
// 第二个参数表示从第 0 个点开始绘制
immediateContext->Draw(3, 0);
swapChain->Present(0, 0);
}
return true;
}
int WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
//初始化
//**注意**:最上面声明的4个指针,在这里作为参数传给InitD3D函数
if (!d3d::initD3D(hinstance,
800,
600,
&renderTargetView,
&immediateContext,
&swapChain,
&device))
{
::MessageBox(0, L"InitD3D() - FAILED", 0, 0);
return 0;
}
if (!SetUp())
{
::MessageBox(0, L"Setup() - FAILED", 0, 0);
return 0;
}
//执行消息循环,将函数Display的指针作为参数传递
d3d::EnterMsgLoop(Display);
Cleanup();
return 0;
}
代码来源
/*************************************************************************
> File Name: Triangle.hlsl
> Author: YLD10
《基于 DirectX11 的 3D 图形程序设计案例教程》
5.2 节程序例子 绘制一个三角形
************************************************************************/
/*
* 顶点着色器 (Vertex Shader)
* float4 为 HLSL 提供的关键字, 表示一个 4 维向量, 每个分量是一个浮点数
* VSMain 为顶点着色器的主函数名, 名字可以任意取
* POSITION 为语义表示符, 在创建输入布局时会用到
* SV_POSITION 为 HLSL 标识符, 表示该函数返回的是一个坐标
* 注意这种函数的声明方法有别于 C/C++, 具体意义如下
* 返回类型 参数类型 参数语义 返回值语义
* ↓ ↓ ↓ ↓
* float4 VSMain(float4 Pos : POSITION) : SV_POSITION
*/
float4 VSMain(float4 Pos : POSITION) : SV_POSITION
{
return Pos;
}
/*
* 像素着色器(Pixel Shader)
* PSMain 为像素着色器的主函数名, 名字可以任意取
* SV_TARGET 为 HLSL 标识符, 表示该函数返回的是一个颜色
*/
float4 PSMain(float4 Pos : POSITION) : SV_TARGET
{
// 返回一个 4 维向量, 分别表示红绿蓝和 alpha, 这里表示三角形是红色的
return float4(1.0f, 1.0f, 0.0f, 1.0f);
}