问题
This is a weird one. I have a fragment shader that as far as I can tell can only return black or red, but it's rendering the pixels in white. And if I remove one specific line, it returns the colour I'd expect. It works in WebGL, but not in OpenGL ES on the Raspberry Pi.
Here's the shader code. It returns black if the pixel represents a point inside the Mandelbrot set, red otherwise.
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);
}
}
So that shader paints all pixels white. However, if I remove the line
runaway = i;
...then, as you'd expect, it paints all pixels black (because it always winds up in the else
branch of the final if
).
Is rendering a white pixel the symptom of some kind of error condition? If so, what could it be?
[edit] Before anyone asks -- setting runaway = 1;
on that line also leads to an all-white screen.
回答1:
I think the problem is that you're doing too much work for a fragment shader for the target device. Your experiments where you set runaway
to i
or 1
are allowing the optimizer to remove the loop entirely which is why you start to see expected results again.
Some relevant quotes from the OpenGL ES Shader Language spec:
In general, control flow is limited to ... loops where the maximum number of iterations can easily be determined at compile time.
To me (and I'm speculating a bit here), this translates as "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.
To me, this is saying, "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
I feel OpenGLES 2 is a bit vague about shader complexity limits. I think the problem is either:
- Your compiled shader is exceeding the instruction count limit for the implementation
- Your shader is taking too long to execute and is getting interrupted at runtime as a result.
I think that if it is #1 you should probably expect shader compiler errors, linker errors or validation errors. Does your code check thoroughly for these? It may clarify the situation a little.
Regardless, I think you'll have to simplify the shader to make it work on Raspberry Pi.
来源:https://stackoverflow.com/questions/44730222/opengl-es-fragment-shader-apparently-impossibly-returning-white