这很奇怪。我有一个片段着色器,据我所知只能返回黑色或红色,但它会将像素渲染为白色。如果我删除一个特定的行,它将返回我期望的颜色。它适用于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
也会导致全白屏幕。
答案 0 :(得分:2)
我认为问题在于你为目标设备的片段着色器做了太多工作。您将runaway
设置为i
或1
的实验允许优化器完全删除循环,这就是您再次开始看到预期结果的原因。
OpenGL ES着色器语言spec中的一些相关引用:
通常,控制流程仅限于......循环,其中可以在编译时轻松确定最大迭代次数。
对我而言(我在这里推测一下),这转化为“某些实现根本不支持迭代,并将展开每个循环”
允许非终止循环。非常长或非终止循环的后果取决于平台。
对我来说,这就是说,“你可以让你的着色器尽可能多地迭代,但不一定能指望它能够工作”。
是否应规定迭代次数的限制?决议:否
我觉得OpenGLES 2对着色器复杂度的限制有点模糊。我认为问题是:
我认为如果它是#1,您可能应该期望着色器编译器错误,链接器错误或验证错误。您的代码是否彻底检查了这些?它可能会略微澄清一下情况。
无论如何,我认为您必须简化着色器才能使其在Raspberry Pi上运行。