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

时间:2017-06-23 21:30:46

标签: opengl-es glsl glsles

这很奇怪。我有一个片段着色器,据我所知只能返回黑色或红色,但它会将像素渲染为白色。如果我删除一个特定的行,它将返回我期望的颜色。它适用于WebGL,但不适用于Raspberry Pi上的OpenGL ES。

这是着色器代码。如果像素表示Mandelbrot集内的一个点,则返回黑色,否则返回红色。

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;

...然后,正如您所期望的那样,它会将所有像素描绘为黑色(因为它总是在最终else的{​​{1}}分支中结束。)

呈现白色像素是某种错误情况的症状吗?如果是这样,它会是什么?

[edit]在有人要求之前 - 在该行上设置if也会导致全白屏幕。

1 个答案:

答案 0 :(得分:2)

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

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

  

通常,控制流程仅限于......循环,其中可以在编译时轻松确定最大迭代次数。

对我而言(我在这里推测一下),这转化为“某些实现根本不支持迭代,并将展开每个循环”

  

允许非终止循环。非常长或非终止循环的后果取决于平台。

对我来说,这就是说,“你可以让你的着色器尽可能多地迭代,但不一定能指望它能够工作”。

  

是否应规定迭代次数的限制?决议:否

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

  1. 您编译的着色器超出了实施的指令数限制
  2. 您的着色器执行时间过长,因此在运行时会中断。
  3. 我认为如果它是#1,您可能应该期望着色器编译器错误,链接器错误或验证错误。您的代码是否彻底检查了这些?它可能会略微澄清一下情况。

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