着色器代码中的for循环使用硬编码数字,但不使用统一变量

问题描述 投票:5回答:3

我在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,但我不想在此处复制并粘贴所有内容。我希望这种保持简短的方法受到赞赏,否则我将把所有内容复制过来。

我期待一个解释:)

谢谢!

android opengl-es-2.0 glsl libgdx vertex-shader
3个回答
11
投票

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


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

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

我猜想,台式机上的硬件比平板电脑上的硬件更先进。希望这会有所帮助!


0
投票

一个有趣的半答案,和/或我选择的基本问题的解决方案。

以下调用带有'id'的函数作为着色器的脚本块的ID传递,并以[[ThingToReplace,ReplaceWith],]字符串格式填充'swaps',其中包含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,这是一种非常类似于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
}
© www.soinside.com 2019 - 2024. All rights reserved.