这是一个奇怪的事情。我有一个片段着色器,据我所知只能返回黑色或红色,但它将像素渲染为白色。如果我删除一根特定的线,它会返回我期望的颜色。它适用于 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;
...然后,如您所料,它将所有像素绘制为黑色(因为它总是出现在最终 if
的 else
分支中)。
渲染白色像素是否是某种错误情况的症状?如果是这样,那会是什么?
[编辑]在任何人询问之前 - 在该行设置 runaway = 1;
也会导致全白屏幕。
最佳答案
我认为问题在于您为目标设备的片段着色器做了太多工作。您将 runaway
设置为 i
或 1
的实验允许优化器完全删除循环,这就是您开始再次看到预期结果的原因.
OpenGL ES 着色器语言的一些相关引用 spec :
In general, control flow is limited to ... loops where the maximum number of iterations can easily be determined at compile time.
对我来说(我在这里推测一下),这可以翻译为“某些实现根本不支持迭代,并且会展开每个循环”
Non-terminating loops are allowed. The consequences of very long or non-terminating loops are platform dependent.
对我来说,这就是说,“你可以让你的着色器按照你喜欢的方式迭代,但不一定期望它能够工作”。
Should a limit on the number of iterations be specified? RESOLUTION: No
我觉得 OpenGLES 2 对于着色器复杂度限制有点模糊。我认为问题在于:
- 您编译的着色器超出了实现的指令数限制
- 您的着色器执行时间过长,因此在运行时被中断。
我认为,如果它是#1,您可能应该预料到着色器编译器错误、链接器错误或验证错误。您的代码是否彻底检查了这些?它可能会稍微澄清一下情况。
无论如何,我认为您必须简化着色器才能使其在 Raspberry Pi 上运行。
关于opengl-es - OpenGL ES 片段着色器显然不可能返回白色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44730222/