在片段着色器中传递variables的问题

我试图从数组中传递一个点光源到一个片段着色器中的CalcLight函数。 它的工作原理是当我硬编码的值,但不是当我使用循环。 代码如下:

#define TOTAL_LIGHTS 2 struct PLight { vec4 pos; vec4 diff; vec4 spec; vec4 amb; float con; float lin; float quad; }; layout(std140) uniform Light { PLight pLights[TOTAL_LIGHTS]; }light; vec3 CalcPoint(in PLight p) { ... } 

当我通过使用硬编码值的主要灯光传递,它工作正常。

 void main() { ... pointLight += CalcPoint(light.pLights[0]); pointLight += CalcPoint(light.pLights[1]); ... } 

但是,当试图使用循环,第一个灯正常工作,但不是第二个。

 for(int i = 0; i < TOTAL_LIGHTS; i++) pointLight += CalcPoint(light.pLights[i]); 

任何想法为什么循环不工作?

该结构不正确,这可能是你的问题的来源。

要使用std140中的PLight来形成一个数组,你需要在最后使用一个额外的float来填充它。 否则, PLight pLights[TOTAL_LIGHTS]没有alignment,您将从pLights [1]获取错误的内存pLights [1] – 在这个结构arrays中,第二个灯光的所有内容都将被closures。

考虑这个,而不是:

 struct PLight { vec4 pos; vec4 diff; vec4 spec; vec4 amb; float con; float lin; float quad; float padding; }; 

整个数组大小需要被填充到std140的多个基准。 在这种情况下,您的基准线是vec4 (4N)。 所以这意味着要满足这种alignment,你需要添加一个float到最后。 GLSL会自动为你做这个,当你在着色器之外的代码中声明这个结构时,这个float padding元素是你需要注意的。

非常量索引到统一数组可能会非常棘手,取决于GLSL版本。 我认为你在做什么应该在规范内(即使对于GLES 2.0),但它仍然可能是问题。 请参阅GLES 2.0 GLSL 1.0规范中关于在fragmen着色器中对统一数组进行索引的说明:

附录第5条

在顶点着色器中,强制支持所有forms的数组索引。 在片段着色器中,对索引的支持只针对常量索引expression式。

常量索引expression式是常量expression式的超集。 常量索引expression式可以包含附录A第4节定义的循环索引。

在桌面上应该会更好,但仍然可能会导致问题,因为你必须指定const。 数组大小(你做的)。

我知道这对于解决问题并没有什么帮助,但是可能会给出一些线索。