问题描述
对于计算多个光源,在GLSL中具有可调整大小的数组(如C ++ std::vector
)将非常方便.数组的大小必须始终能够变化,而无需重新编译着色器.
For calculating multiple light sources it would be extremely handy to have resizable arrays in GLSL like the C++ std::vector
. The size of the array has to be able to change all the time, without recompiling the shader.
是否有一些命令,库等可以做到这一点?
Is there some command, library etc. that can do this?
推荐答案
vector
并不是魔术.它通过分配内存来工作. GLSL中没有内存分配.着色器使用它有权访问的资源.不允许着色器仅创建资源.
vector
isn't magic; it works by allocating memory. There is no memory allocation in GLSL; a shader uses the resources it is given access to. Shaders aren't allowed to just create resources.
解决此问题的典型方法是创建一个统一数组,该数组中包含最大数量的灯光,然后您提供一个单独的制服,告诉着色器其中该数组中有多少灯光包含真实数据.本质上,您要预先分配一个固定大小的缓冲区,该固定大小表示您可以使用的最大灯光数量.
The typical way this is solved is by creating a uniform array that has some maximum number of lights in it, and you provide a separate uniform that tells the shader how many lights in that array have real data in them. Essentially, you're pre-allocating a fixed size buffer, and that fixed-size represents the maximum number of lights you can work with.
通常没关系.如果您的灯光多于固定大小限制,那么您需要为其余灯光添加更多的灯光通道(如果您有那么多灯光,则应该或应该使用延迟渲染).
That's normally just fine. If you have more lights than the fixed-size limitation, then you'll need to add additional lighting passes for the rest (if you have that many lights, you are, or should be, using deferred rendering).
通常,此类固定大小的数组是UBO的一部分,因此您可以轻松地对其进行更新并换出.与常规的GLSL制服相比,UBO的限制也更大.
Typically, such fixed-sized arrays are part of UBOs, so that you can easily update them and swap them out. UBOs also have larger limits than regular GLSL uniforms.
如果您出于某些原因绝对需要任意限制,则可以使用包含照明数据的SSBO. SSBO可以静态调整大小:
If you absolutely need to have arbitrary limits (for some reason), then you can use an SSBO containing your lighting data. SSBOs can be statically unsized:
layout(binding = #, std430) buffer light_data
{
Light lights[];
};
lights
中的条目数将由Light
的大小以及与SSBO缓冲区绑定索引#
关联的缓冲区范围中的字节数确定.因此,如果Light
是32字节大,并且您应用了8192字节的缓冲区范围,那么lights.length()
将返回256个条目.
The number of entries in lights
will be determined by the size of Light
and the number of bytes in the buffer range you associate with the SSBO buffer binding index #
. So if Light
is 32 bytes large, and you apply a buffer range of 8192 bytes, then lights.length()
will return 256 entries.
话虽如此,您应该真正尝试在UBO限制范围内生活. UBO访问可能比SSBO更快,因为它们在执行着色器之前(在某些硬件中)直接加载到着色器内存中.相比之下,SSBO始终是全局内存访问.
That being said, you should really try to live within the UBO limitations. UBO accesses can be faster than SSBOs, since they are (in some hardware) loaded directly into shader memory before executing shaders. By contrast, SSBOs are always global memory accesses.
这篇关于GLSL中的可调整大小的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!