我正在使用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
在应用程序开始时给一个很大的价值,并向数组添加灯光,但是我发现这种方法复杂,固定且效率不高。
有人知道如何解决这个问题吗?先感谢您。
从着色器访问可变大小数组(具有运行时定义的大小)的一般问题可能会以不同的方式解决,具体取决于数组大小,数据更改的频率以及您要定位的硬件。
我想到了几种技术:
如果您的数组很小,那么最简单的方法就是按照您的建议传递一个带有固定大小的数组和当前大小的常量缓冲区。
在几乎所有硬件上都可以使用的方法是将数据写入纹理,然后从着色器采样或加载。您只能读取基本类型(float
,float4
等),因此需要对纹理实施适当的索引以读取复杂的对象struct
。
在Shader Model 5硬件上(以及在某些SM 4上),您可以使用UAV
s和StructuredBuffer
s从缓冲区读取结构化数据。
如果您有涉及数组的真正复杂的计算,并且如果目标硬件允许这样做,则可能需要将处理移至Compute Shader或什至OpenCL或CUDA内核。
考虑到给定的问题,即经典照明,我想说我所看到的99%使用方法1。无论如何,您实际上在大多数情况下在场景中实际上并没有十多个灯。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句