我在this question中请求帮助解决OpenGL ES 2.0问题。 似乎答案对我来说很奇怪。 因此,我决定提出这个问题,希望能够理解正在发生的事情。
以下是错误的顶点着色器代码:
// a bunch of uniforms and stuff...
uniform int u_lights_active;
void main()
{
// some code...
for ( int i = 0; i < u_lights_active; ++i )
{
// do some stuff using u_lights_active
}
// some other code...
}
我知道这看起来很奇怪但这实际上是解释问题/错误行为所需的所有代码。
我的问题是:当我为u_lights_active传递一些大于0的值时,为什么循环没有被执行? 当我硬编码一些整数,例如4,而不是使用统一的u_lights_active,它工作正常。
还有一件事,这只出现在Android上,但不出现在桌面上。我使用LibGDX在两个平台上运行相同的代码。
如果需要更多信息,您可以查看original question,但我不想复制并粘贴所有内容。 我希望这种保持简短的方法是值得赞赏的,否则我会把所有的东西都复制过来。
我期待着一个解释:)
谢谢!
答案 0 :(得分:10)
基本上,GLSL指定实现可以限制循环对它们具有“常量”界限。这是为了简化优化代码并行运行(不同像素的不同循环计数会很复杂)。我相信在一些实现中,常量甚至必须很小。请注意,规范只是指定了“最小”行为,因此某些设备可能支持比规范要求更复杂的循环控制。
以下是约束的一个很好的总结: http://www.khronos.org/webgl/public-mailing-list/archives/1012/msg00063.html
这是GLSL规范(见附录A第4节): http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf
答案 1 :(得分:2)
http://www.opengl.org/discussion_boards/showthread.php/171437-can-for-loops-terminate-with-a-uniform
http://www.opengl.org/discussion_boards/showthread.php/177051-GLSL-loop-problem-on-Radeon-HD-cards
https://www.opengl.org/discussion_boards/showthread.php/162535-variable-controlled-for-loops
如果你有一个静态循环,它可以展开并进入静态常量查找。如果您绝对需要将其设置为动态,则需要将索引数据存储到1D纹理中并进行采样。
我猜测桌面硬件比平板电脑更先进。希望这有帮助!
答案 2 :(得分:0)
有一个有趣的半答案,或者,或者是我选择的基本问题的解决方案。
以下调用的函数带有'id'作为着色器的脚本块的ID,而'swaps'则由2个组成为[[ThingToReplace,ReplaceWith],]字符串格式的数组组成。在创建着色器之前调用。
在javascript中:
var ReplaceWith = 6;
function replaceinID(id,swaps){
var thingy = document.getElementById(id);
for(var i=0;i<swaps.length;i++){
thingy.innerHTML = thingy.innerHTML.replace(swaps[i][0], swaps[i][1]);
}
}
replaceinID("My_Shader",[['ThingToReplace',ReplaceWith],]);
来自C,这是一种非常类似于Macro的方法,因为它模拟了预处理器。
在GLSL中:
for(int i=0;i<ThingToReplace;i++){
;//whatever goes here
}
或者;
const int val = ThingToReplace;
for(int i=0;i<val;i++){
;//whatever goes here
}