D3D11:HLSL 中可变数量的灯
D3D11: variable number of lights in HLSL
我正在使用 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 or Load写入数据。您只能读取基本类型(float
、float4
等),因此您需要对纹理实施适当的索引以读取复杂对象(struct
s)。
在 Shader Model 5 硬件上(以及一些 SM 4 上)您可以使用 UAV
s and StructuredBuffer
s 从缓冲区读取结构化数据。
如果您有涉及数组的非常复杂的计算,并且如果目标硬件允许您这样做,您可能希望将处理移动到计算着色器甚至 OpenCL 或 CUDA 内核。
考虑到给定的问题,即经典光照,我会说我所见的 99% 都使用方法 1。大多数情况下,一个场景中的灯光实际上不会超过一打.
我正在使用 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 or Load写入数据。您只能读取基本类型(
float
、float4
等),因此您需要对纹理实施适当的索引以读取复杂对象(struct
s)。在 Shader Model 5 硬件上(以及一些 SM 4 上)您可以使用
UAV
s andStructuredBuffer
s 从缓冲区读取结构化数据。如果您有涉及数组的非常复杂的计算,并且如果目标硬件允许您这样做,您可能希望将处理移动到计算着色器甚至 OpenCL 或 CUDA 内核。
考虑到给定的问题,即经典光照,我会说我所见的 99% 都使用方法 1。大多数情况下,一个场景中的灯光实际上不会超过一打.