Original issue: https://code.google.com/p/chrome-os-partner/issues/detail?id=22417
Per david.garbett@arm.com at comment #3:
This is another shader precision issue, in the fragment shader.
I found that adding the highp qualifier to the v_position varying in the "skyboxFragmentShader" was enough to fix the demo.
Comment #1
Posted on Oct 17, 2013 by Helpful LionI'm sorry, but this is a bug in the OpenGL driver on this device, not the shader. The GLSL ES 1.0.17 spec says in section 4.3.5 "Varying":
"The type of varying variables with the same name declared in both the vertex and fragment shaders must match, otherwise the link command will fail. The precision of varying variables does not need to match."
highp support in fragment shaders is optional. The fact that the varying vec4 v_position is implicitly highp in the vertex shader and mediump in the fragment shader is not an error and the driver is required to handle this. This demo works fine on other ES 2.0 devices.
Closing as WontFix.
Comment #2
Posted on Oct 18, 2013 by Massive MonkeyI'm sorry, but this does appear to be a bug in the demo, but not in the demo's shader.
When setting up the skybox, the demo creates an xz-plane, and then reorients it to an xy-plane located at z=0.9999.
The value 0.9999 as a single precision float (IEEE 754) is 0.9998999834060669, with a 23-bit mantissa: 0x3f7ff972 == 0.7e.7ff972 == 0.126.8386930 (sign.exponent.mantissa) +1 * 2^(-1) * 1.9997999668121338
This is the highp value of the position uniform in the vertex shader.
When the value is passed to the mediump fragment shader, however, its mantissa will gets truncated to a 10-bit value (per the WebGL spec, Relative FP precision is 2^(-10)).
Thus any value >= 0.999755859375 (mantissa: 0x7ff000 == 8384512) gets mapped to the mediump value 1.0.
Hence, in the fragment shader, the plane appears to be at z=1.0, and thus the texture is not visible.
AFAICT, the driver is not at fault here. Updating the skybox z position to 0.9997 (or just 0.999) should make it compatible with ES 2.0 devices that actually implement mediump with an FP Precision of 2^(-10). Perhaps the other ES 2.0 devices on which this demo have been tested were not really using FP Precision of 2^(-10).
Comment #3
Posted on Oct 18, 2013 by Massive Rhinokbr@ - I'm afraid I have to agree with djkurtz@ that this is still a demo bug.
For reference, here's the skyboxFragmentShader:
ifdef GL_ES
precision mediump float;
endif
uniform samplerCube skybox; uniform mat4 viewDirectionProjectionInverse; varying vec4 v_position; void main() { vec4 t = viewDirectionProjectionInverse * v_position; gl_FragColor = textureCube( skybox, normalize(t.xyz / t.w)); }
I believe the problem is not with the varying |v_position|, but (as pointed out in #12) is in fact that the view projection matrix is of medium precision. This is the "uniform mat4 viewDirectionProjectionInverse" in the frag shader above.
IMHO the fact that demo is "fixed" by promoting |v_position| to highp is a conincidence - because when calculating vec4 t = viewDirectionProjectionInverse * v_position, the mali driver decides to promote result |t| to highp if either operand is highp.
Instead of forcing |v_position| to highp, the demo can also be fixed if we force |viewDirectionProjectionInverse| to highp.
Also, I have tried to modify mali-drivers to always promote varying precision to the higher of the frag/vert symbol, but it doesn't fix the problem.
Comment #4
Posted on Oct 19, 2013 by Helpful Liondjkurtz@: thank you for the detailed analysis. I agree with you that it's a precision problem and that the workaround is to use a smaller constant. This has been fixed in https://code.google.com/p/webglsamples/source/detail?r=5c4b108e29d8cac1f1d2dbc298952a0310c08a8e and the result should show up on the served web pages shortly.
Status: Fixed
Labels:
Type-Defect
Priority-Medium