6

I asked for help about an OpenGL ES 2.0 Problem in this question. What seems to be the answer is very odd to me. Therefore I decided to ask this question in hope of being able to understand what is going on.

Here is the piece of faulty vertex-shader code:

// 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...
}

I know this looks odd but this is really all code that is needed to explain the problem / faulty behavior.

My question is: Why is the loop not getting executed when I pass in some value greater 0 for u_lights_active? When I hardcode some integer e.g. 4, instead of using the uniform u_lights_active, it is working just fine.

One more thing, this only appears on Android but not on the Desktop. I use LibGDX to run the same code on both platforms.

If more information is needed you can look at the original question but I didn't want to copy and paste all the stuff here. I hope that this approach of keeping it short is appreciated, otherwise I will copy all the stuff over.

I am looking forward to an explanation :)

Thanks!

4

3 回答 3

12

基本上 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

于 2013-09-20T21:57:37.287 回答
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

http://www.opengl.org/discussion_boards/showthread.php/162722-Problem-when-using-uniform-variable-as-a-loop-count-in-fragment-shader

https://www.opengl.org/discussion_boards/showthread.php/162535-variable-controlled-for-loops

如果你有一个静态循环,它可以展开并变成静态常量查找。如果您绝对需要使其动态化,则需要将索引数据存储到 1D 纹理中并对其进行采样。

我猜桌面上的硬件比平板电脑上的更先进。希望这可以帮助!

于 2013-09-20T21:13:56.233 回答
0

一种有趣的半答案,或者,我选择的潜在问题的解决方案。

下面的函数调用了 'id' 作为着色器脚本块的 ID 和 'swaps' 填充了 [[ThingToReplace, ReplaceWith],] 字符串格式的 2 个组件数组的数组。在创建着色器之前调用。

在 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,这是一种非常类似于宏的方法,因为它模拟了预处理器。

在 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
}
于 2019-12-27T14:53:01.530 回答