Resizable arrays in GLSL

2020-04-14 11:34发布

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?

1条回答
倾城 Initia
2楼-- · 2020-04-14 12:18

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).

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.

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[];
};

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.

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.

查看更多
登录 后发表回答