我正在使用 C++ 和 Direct3D11 开发游戏引擎,现在我想向场景中添加可变数量的灯光。到目前为止,我设法添加和渲染了一些已知的并在着色器程序中编码的简单灯光。
在 shader.fx 中:
static const int LightsCount= 4;
struct NF3D_LIGHT
{
// Members...
};
cbuffer Light : register(b5)
{
NF3D_LIGHT light[LightsCount];
};
...
// And the pixel shader function:
float4 PS(PS_INPUT input) : SV_Target
{
for(int i = 0; i < LightsCount; i++)
{
// Process each light and return the final pixel colour
}
}
这很好用。但如果我尝试:
cbuffer LIGHTS_COUNT : register(b13)
{
int LightsCount;
}
要使灯的数量根据游戏中发生的情况而变化,这是行不通的。我知道我可以在应用程序开始时给 LightsCount
一个很大的值并向数组添加灯光,但我发现这种方法复杂、固定且效率不高。
有人知道如何解决这个问题吗?提前谢谢你。
最佳答案
从着色器访问可变大小数组(具有运行时定义的大小)的一般问题可能会以不同的方式解决,具体取决于数组大小、数据更改频率和您的目标硬件。
我想到了几种技术:
如果您的数组很小,最简单的方法就是按照您的建议传递一个具有固定大小数组 和当前大小 的常量缓冲区。
几乎在任何硬件上都适用的方法是将数据写入纹理 和Sample或 Load它来自着色器。您只能读取基本类型(
float
、float4
等),因此您需要对纹理实现适当的索引以读取复杂对象(结构
)。在 Shader Model 5 硬件上(以及一些 SM 4 上)你可以使用
UAV
s 和StructuredBuffer
s 从缓冲区读取结构化数据。如果您有涉及数组的非常复杂的计算,并且如果目标硬件允许您这样做,您可能希望将处理转移到计算着色器,甚至转移到 OpenCL 或 CUDA 内核。
<
考虑到给定的问题,即经典光照,我会说我所见的 99% 都使用方法 1。无论如何,大多数时候一个场景中的灯光不会超过一打。
关于c++ - D3D11 : variable number of lights in HLSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34456099/