我正在研究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
一个大值,并为数组添加灯光,但我发现这个方法很复杂,固定且效率不高。
有人知道如何解决这个问题吗?提前谢谢。
答案 0 :(得分:3)
从着色器访问可变大小数组(具有运行时定义的大小)的一般问题可能会有所不同,具体取决于数组大小,数据更改频率和您要定位的硬件。
有几种技巧可以想到:
如果你的数组很小,最简单的方法就是按照你的建议传递一个带有固定大小数组和当前大小的常量缓冲区。
几乎可以在任何硬件上运行的方法是从着色器中将数据写入纹理和Sample或Load。您只能读取基本类型(float
,float4
等),因此您需要在纹理中实现正确的索引以读出复杂对象(struct
s)。 / p>
在Shader Model 5硬件上(以及某些SM 4上),您可以使用UAV
和StructuredBuffer
来读取缓冲区中的结构化数据。
如果您有涉及数组的非常复杂的计算,并且目标硬件允许您这样做,您可能希望将处理移至Compute Shader或甚至OpenCL或CUDA内核。
考虑到给定的问题,即经典照明,我会说我见过的99%使用方法1.无论如何,你在场景中并没有真正拥有超过十几个灯光。 / p>