OpenGL ES 片段着色器显然不可能返回白色

OpenGL ES fragment shader apparently impossibly returning white

这很奇怪。我有一个片段着色器,据我所知只能 return 黑色或红色,但它以白色渲染像素。如果我删除一个特定的行,它 return 就是我期望的颜色。它适用于 WebGL,但不适用于 Raspberry Pi.

上的 OpenGL ES

这是着色器代码。如果像素表示 Mandelbrot 集中的一个点,则它 return 为黑色,否则为红色。

precision mediump float;

varying vec2 vPosition;

void main(void) {
    float cx = vPosition.x;
    float cy = vPosition.y;

    float x = 0.0;
    float y = 0.0;
    float tempX = 0.0;
    int runaway = 0;
    for (int i=0; i < 100; i++) {
         tempX = x * x - y * y + float(cx);
         y = 2.0 * x * y + float(cy);
         x = tempX;
         if (runaway == 0 && x * x + y * y > 100.0) {
             runaway = i;
         }
    }

    if (runaway != 0) {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    } else {
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }
}

因此着色器将所有像素绘制为白色。但是,如果我删除行

             runaway = i;

...然后,如您所料,它将所有像素涂成黑色(因为它总是在最终 ifelse 分支中结束)。

渲染白色像素是某种错误情况的征兆吗?如果是这样,它会是什么?

[edit] 在任何人问之前——在该行设置 runaway = 1; 也会导致全白屏幕。

我认为问题在于您为目标设备的片段着色器做了太多工作。您将 runaway 设置为 i1 的实验允许优化器完全删除循环,这就是您开始再次看到预期结果的原因。

OpenGL ES 着色器语言中的一些相关引用spec

In general, control flow is limited to ... loops where the maximum number of iterations can easily be determined at compile time.

对我来说(我在这里有点猜测),这翻译为 "Some implementations don't support iteration at all and will unroll every loop"

Non-terminating loops are allowed. The consequences of very long or non-terminating loops are platform dependent.

对我来说,这就是说,"You can make your shader iterate as much as you like but shouldn't necessarily expect it to work"。

Should a limit on the number of iterations be specified? RESOLUTION: No

我觉得 OpenGLES 2 对着色器复杂度限制有点含糊。我认为问题是:

  1. 您编译的着色器超出了实现的指令数限制
  2. 您的着色器执行时间过长,因此在运行时被中断。

我认为,如果它是 #1,您可能应该预料到着色器编译器错误、链接器错误或验证错误。您的代码是否彻底检查了这些?它可能会稍微澄清一下情况。

无论如何,我认为您必须简化着色器才能使其在 Raspberry Pi 上运行。