1
$\begingroup$

gradients

I am making multiple gradients with GLSL. However, when I started using a loop instead of a lengthy else if condition, the compile time jumped from 2-4sec to 40sec !

// (simplified code)

vec3 gradient(vec3 from, vec3 to, float cursor, int colorSpace) {
    vec3 color;

    // !! The more switch case there are, the slower it gets, but only perceptible when using a loop (in getBackgroundColor function bellow)
    switch(colorSpace) {
        case 0:
            color = mix(
                from,
                to,
                cursor
            );
            break;
        case 1:
          // return gradient, but using Oklab colors
        case 2:
          // return gradient but using IPT colors, etc

        // ... up to 13
    }

    return color;
}

vec4 getBackgroundColor (vec2 uv, EffectOptions opt) {
    vec3 color;

    if (opt.effect == 0) {
        // transparent
    } else if (opt.effect == 1) {
        // pattern from image
    } else if (opt.effect == 2) {
        // gradient
        color = gradient(
            opt.color0,
            backgroundColor,
            uvxCursor,
            opt.gradientColorSpace
        );
    } else if (opt.effect == 3) { // debug gradients by showing all of them
        uv.y = -uv.y;
        uv += 1.;
        uv/= 2.;

        float uvxCursor = clamp(uv.x, 0., 1.);

        int totalBand = 13; // !! totalBand can be 2, it doesn't seem to changes the compile time at all

        // Simple loop to avoid a lengthy elseif
        // !! Extremely slow: 40sec compilation time. What is wrong with this loop ??
        for (int i = 0; i < totalBand; i++) {
            if (uv.y < float(i+1)/float(totalBand)) {
                color = gradient(
                    opt.color0,
                    backgroundColor,
                    uvxCursor,
                    i
                );
                break;
            }
        }
    }
    // else... up to 10

    return vec4(color, 1.);
}

If I use a else if statement like bellow, the compilation goes back to 2sec.

        if (uv.y < 1./13.) {
                    color = gradient(
                        opt.color0,
                        backgroundColor,
                        uvxCursor,
                        0
                    );
        } else if (uv.y < 2./13.) {
            color = gradient(
                opt.color0,
                backgroundColor,
                uvxCursor,
                1
            );
        } // ... up to 13

I have seen this answer https://stackoverflow.com/questions/54408908/custom-shader-material-taking-forever-to-initialize , and it might have something to do with "dynamic branching".

But I am quite new to shaders and have a limited understanding. Is there something obviously wrong with using a loop that I am not seeing ?

PS: I am also using ThreeJS version v135 right now (not the latest). I don't think it is an issue, but if nobody sees an issue with the loop above, then I will have to think outside the box.

PS 2: I profiled my web page, and I think the issue is 99% likely to come from GLSL compilation based on https://discourse.threejs.org/t/getprograminfolog-performance-issue/41069

$\endgroup$
1
  • 1
    $\begingroup$ Loops are unrolled in GLSL last time I checked, so can have a noticable bearing on compilation times, shader size (footprint), and ultimately execution times. Branching in shaders certainly doesn't seem to have to overhead that it used to so may be preferable overall, if you can do it in a manageable way. $\endgroup$
    – lfgtm
    Apr 24, 2023 at 15:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.