D3D11绘制三角形

// 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); }

 

图片

 

posted on 2025-08-20 19:37  邗影  阅读(13)  评论(0)    收藏  举报

导航