【问题标题】:OpenGL uniform nof found if uniform block gets too big如果统一块变得太大,则找不到 OpenGL 统一
【发布时间】:2017-06-16 12:33:16
【问题描述】:

我正在尝试实现统一块。

这是块在我的片段着色器中的样子:

struct Light {
    uint LightType;
    vec3 Direction;
    float SpotBlur;
    vec3 AmbientColor;
    float LinearAttenuation;
    vec3 DiffuseColor;
    float QuadraticAttenuation;
    vec3 SpecularColor;
    float CubicAttenuation;
    vec3 Position;
    float SpotCutoff;
};

layout(std140) uniform LightBlock
{
    Light values;
} lights[32];

如您所见,我定义了一个固定大小为 32 的 Light 结构数组。我可以毫无问题地上传数据,但现在出现了我不明白的问题。 如果“灯光”数组的尺寸相对较小(大约 6 个),我的所有着色器制服都会找到。但是当增加“灯”的大小时,它开始有点覆盖我的制服。例如,它再也无法从顶点着色器中找到我的“modelViewProjection”矩阵(返回 -1 作为统一位置)。

【问题讨论】:

  • 我不确定你想要实现什么,但如果你想用统一的缓冲区支持 LightBlock,[32] 不应该属于values 而不是lights ?目前您定义了 32 个块,而不是具有 32 个条目的块。
  • @bitQuake: 请stop using vec3 in interface blocks. 尤其是您的布局真的 很糟糕,因为在每个float/int 之后,有12 个字节的填充(@987654329 @ 对齐到 16 个字节)。

标签: opengl glsl buffer shader uniform


【解决方案1】:

问题

OpenGL 通过 MAX_VERTEX_UNIFORM_COMPONENTS_ARB 来限制统一数组的大小。 据我所知,这通常设置为 2048 或 4096,因此分别设置为 512 或 1024 字节限制。 (这取决于图形硬件)
一个 Light 对象当前使用 84 字节的数据。
问题是当您创建一个包含 32 个这样的对象的数组时,会使用 2688 字节的数据。
大小为 6 的原因是因为 84*6 是 504,即

修复

不幸的是,根据我的研究,这个限制似乎是由硬件强加的,除非您切换到具有不同限制的显卡(或者可能通过创建自定义图形来更改 OpenGL 实现),否则无法更改它司机)。解决问题的最简单方法是 减小灯光阵列的大小或减小灯光对象的大小(或两者结合)。

编辑:感谢 BDL 关于使用 UBO 或 SSBO 的出色建议。他是正确的,这些将允许您通过更大的制服。我还编辑了我的答案以反映 MAX_VERTEX_UNIFORM_COMPONENTS 的真实定义。

@bitQUAKE 提出了一个使用不同大小限制的解决方法:
检查下面的 cmets 以获得他的解决方案。 Here 是该主题的相关讨论。

【讨论】:

  • 您还应该补充一点,使用 UBO 或 SSBO 可以解决问题,因为它们有自己的大小限制。另请注意,MAX_VERTEX_UNIFORM_COMPONENTS 不返回以字节为单位的大小。它返回可以保存在统一内存中的变量数。最低要求是在 OpenGL 4.5 1024 中。
  • 感谢您的建议和指正。我已经更新了我的答案。
  • @KylonTyner 感谢您的回答。正如您告诉我减少灯光数组一样,我尝试制作一个“灯光值”数组; (例如:values[32])效果很好。看起来这不是 MAX_VERTEX_UNIFORM_COMPONENTS 的一部分,而是 GL_MAX_UNIFORM_BLOCK_SIZE。也许你可以用这个解决方法更新你的答案:)
猜你喜欢
  • 2020-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
相关资源
最近更新 更多