在DirectX 12中使用geometry shader

Posted 异次元的归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在DirectX 12中使用geometry shader相关的知识,希望对你有一定的参考价值。

几何着色器可以允许我们在GPU中增加,删除,修改传入的顶点属性。一个常见的用途是billboard,视野远处的物体直接用一个永远面向摄像机的面片来代替,并且这个面片实际上可以由1个点通过几何着色器输出4个顶点来生成。

首先,我们需要定义新的顶点类型,和相应的input layout:

	struct PointVertex
	{
		XMFLOAT3 position;
		XMFLOAT2 size;
	};

	mPointInputLayout =
	{
		{"POSITION",	0,	DXGI_FORMAT_R32G32B32_FLOAT,	0,	D3D12_APPEND_ALIGNED_ELEMENT,	D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,	0},
		{"SIZE",		0,	DXGI_FORMAT_R32G32_FLOAT,		0,	D3D12_APPEND_ALIGNED_ELEMENT,	D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,	0}
	};

由于新增了一种顶点类型,也需要新增对应该类型的vertex buffer和vertex buffer view:

	ThrowIfFailed(mDevice->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
		D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(mVertexBufferSize * sizeof(PointVertex)),
		D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&mPointVertexBufferGPU)));
	
	mPointVertexBufferView.BufferLocation = mPointVertexBufferGPU->GetGPUVirtualAddress();
	mPointVertexBufferView.SizeInBytes = mVertexBufferSize * sizeof(PointVertex);
	mPointVertexBufferView.StrideInBytes = sizeof(PointVertex);

为了使用geometry shader,我们需要在编译的时候把它带进去:

D3DCompileFromFile(srcFile.c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, "GS", "gs_5_0", compileFlags, 0, gs, &error);

相应地,需要创建一个新的pipeline state object:

D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
psoDesc.GS = { gs->GetBufferPointer(), gs->GetBufferSize() };
psoDesc.InputLayout = { mPointInputLayout.data(), mPointInputLayout.size() };
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;

值得一提的是,我们可能希望为不同的billboard设置不同的texture。而设置texture需要在绘制不同的object时设置不同的shader resource view。为了避免频繁切换view,可以使用texture2darray,将相关的texture合并起来:

		srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
		srvDesc.Format = res->GetDesc().Format;
		srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
		srvDesc.Texture2DArray.ArraySize = res->GetDesc().DepthOrArraySize;
		srvDesc.Texture2DArray.FirstArraySlice = 0;
		srvDesc.Texture2DArray.MipLevels = -1;
		srvDesc.Texture2DArray.MostDetailedMip = 0;
		srvDesc.Texture2DArray.PlaneSlice = 0;
		srvDesc.Texture2DArray.ResourceMinLODClamp = 0.0f;

这里用到的geometry shader的函数声明如下:

[maxvertexcount(4)]
void GS(point VertexOut gin[1],
	uint primID : SV_PrimitiveID,
	inout TriangleStream<GeoOut> triStream)

如果你觉得我的文章有帮助,欢迎关注我的微信公众号(大龄社畜的游戏开发之路-

以上是关于在DirectX 12中使用geometry shader的主要内容,如果未能解决你的问题,请参考以下文章

DirectX 12 中 Assimp 的骨骼动画错误

DirectX 12 应用程序在 Windows 11 中崩溃

DirectX/C++ 3D 引擎编程:立即学习,还是等待 DirectX 12? [关闭]

UWP 硬件视频解码 - DirectX12 与 Media Foundation

DirectX 12和DirectX 11选哪个,有什么区别

亲爱的 IMGUI 和 DirectX 12 覆盖 (DXGI_ERROR_INVALID_CALL)