for-loop in shader code working with hardcoded number but not with uniform variable
Asked Answered
S

3

8

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.

Scotney answered 20/9, 2013 at 20:48 Comment(0)
G
14

Basically GLSL specifies that implementations may restrict loops to have "constant" bounds on them. This is to make it simpler to optimize the code to run in parallel (different loop counts for different pixels would be complex). I believe on some implementations the constants even have to be small. Note that the spec just specifies the "minimum" behavior, so some devices might support more complex loop controls than the spec requires.

Here's a nice summary of the constraints: http://www.khronos.org/webgl/public-mailing-list/archives/1012/msg00063.html

Here's the GLSL spec (look at section 4 of Appendix A): http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf

Graves answered 20/9, 2013 at 21:57 Comment(0)
C
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

If you have a static loop it can be unrolled and made into static constant lookups. If you absolutely need to make it dynamic, you'll need to store indexed data into a 1D texture and sample that instead.

I'm guessing that the hardware on the desktop is more advanced than on the tablet. Hope this helps!

Cerous answered 20/9, 2013 at 21:13 Comment(0)
K
0

Kind of a fun half-answer, and-or, the solution to the underlying problem that I have chosen.

The following function called with 'id' passed as the ID of the shader's script block and 'swaps' filled with an array of 2 component arrays in the format of [[ThingToReplace, ReplaceWith],] strings. Called before the shader is created.

In the 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],]);

Coming from C, this is a very Macro like approach, in that it simulates a preprocessor.

In the GLSL:

for(int i=0;i<ThingToReplace;i++){
    ;//whatever goes here
}

Or;

const int val = ThingToReplace;

for(int i=0;i<val;i++){
    ;//whatever goes here
}
Karonkaross answered 27/12, 2019 at 14:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.