wjc272008 / jmonkeyengine

Automatically exported from code.google.com/p/jmonkeyengine
0 stars 0 forks source link

Vertex shaders on Android use 16-bit precision for floats #483

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Load a model with lots of detail and set cull distance to really far 
(greater than 65000)

What is the expected output? What do you see instead?
Notice that model disappear earlier than it should and also that it rendering 
artifacts (pixels shining through)
This can be fixed by using high precision (highp) for floats in the Android 
vertex shaders.

Original issue reported on code.google.com by ShadowIs...@gmail.com on 26 Mar 2012 at 7:34

GoogleCodeExporter commented 9 years ago
"This can be fixed by using high precision (highp) for floats in the Android 
vertex shaders."
 - Do you have a quick fix for this?

Original comment by Adam.Hon...@gmail.com on 27 Mar 2012 at 1:54

GoogleCodeExporter commented 9 years ago

Original comment by ShadowIs...@gmail.com on 6 Sep 2012 at 6:12

GoogleCodeExporter commented 9 years ago
@Kirill there is no such thing as "the Android vertex shaders". vertex shaders 
are common to Desktop and Android.
highp is only supported on opengl es so we can't use it on desktop.
How do you suggest we handle this?
Should we have separated shaders for android?

Original comment by remy.bou...@gmail.com on 22 Dec 2012 at 3:27

GoogleCodeExporter commented 9 years ago
@remy: In the OGLES renderer, we specify the directive "precision mediump 
float" in all shaders:
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/android/co
m/jme3/renderer/android/OGLESShaderRenderer.java#777

This tells GLSL to use medium precision for all variables without a precision 
qualifier - the spec defines mediump float as having a range of -16384 to 
16384. This is TOO LOW for many types of applications, such as space 
simulators, and in general will result in odd artifacts in some cases. For 
proper rendering, jME3 must use highp float for all POSITION vectors, in the 
vertex or fragment shader. This includes point light positions, vertex 
positions, etc, such that subtracting or computing the direction between 
position vectors provides a usable result. As a proper solution to this issue, 
I recommend specifying the "precision mediump float" ONLY in fragment shaders, 
and not specify ANY precision qualifier for the vertex shader. Under the GLSL 
spec, the default precision qualifier in the vertex shader is highp float 
(whereas for fragment shaders, you must declare it manually). 
As a better fix to this issue, I recommend defining new datatypes that indicate 
high precision, e.g. 

#ifdef GL_ES
#define highpfloat highp float
#define highpvec2 highp vec2
#define highpvec3 highp vec3
#define highpvec4 highp vec4
#else
#define highpfloat float
#define highpvec2 vec2
#define highpvec3 vec3
#define highpvec4 vec4
#endif

These new datatypes shall be used in all shaders for position vectors, to 
ensure accurate computations where they are required.

Original comment by ShadowIs...@gmail.com on 26 Dec 2012 at 4:37

GoogleCodeExporter commented 9 years ago
sounds good

Original comment by remy.bou...@gmail.com on 26 Dec 2012 at 6:39

GoogleCodeExporter commented 9 years ago
Or...we use shader nodes and just have a glslEsGenerator that append the 
precision qualifier.
This way it will only be appended to the shader if it's used with opengles.
Since those qualifiers have no effect on non ES glsl, we don't need them there.
Users will be able to set the precision in the j3md declaration.

Original comment by remy.bou...@gmail.com on 8 Feb 2013 at 2:48

GoogleCodeExporter commented 9 years ago
I dug more into this issue.
Actually it may be more difficult than that.

The problem is, devices don't always support high precision float for the 
fragment shader because the specs make it optional.
Also specs requirement for range and precision are very low (16 bit float 
minimum for highp). So even highp may be not enough on some devices.

you can check what's supported with a gles call to glGetShaderPrecisionFormat.
I've checked and for example, my Asus transformer table does not support highp 
for fragment shader.
It supports it for vertex and has a 23 bit precision range for highp, 13 for 
meduimp and 8 for lowp.

My nexus 4 however, supports everything and has the same precision bit size for 
every precision qualifier (24 bits). (i guess newer device will tend to do the 
same)

On the glsl spec side, default precision for vertex shader are
precision highp float;
precision highp int;
precision lowp sampler2D;
precision lowp samplerCube;

and for fragment 
precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;

Also quoting the specs : 
"4.5.4  Available Precision Qualifiers
The built-in macro GL_FRAGMENT_PRECISION_HIGH is defined to one on systems 
supporting highp
precision in the fragment language
#define GL_FRAGMENT_PRECISION_HIGH 1
and is not defined on systems not supporting highp precision in the fragment 
language.  When defined,
this macro is available in both the vertex and fragment languages.  The highp 
qualifier is an optional
feature in the fragment language and is not enabled by #extension."

From that I don't really get if we have to define it when the drivers claim to 
support it or if it's automatically defined...

So default mediump float for fragment only sounds good.

On a side note, i've notice precision issue on the fragment side when you use 
scaled texture coordinates with repeated textures, or animated textures (by 
offsetting the coord with the g_Time). 

Original comment by remy.bou...@gmail.com on 20 Feb 2013 at 10:09

GoogleCodeExporter commented 9 years ago
Isn't 23 bits precision 32-bit float? Regardless of that, jME3 should *always* 
use highp for vertex or light positions. Once that is done the issue is 
resolved as far as I am concerned.

Original comment by ShadowIs...@gmail.com on 21 Feb 2013 at 4:21

GoogleCodeExporter commented 9 years ago
idk for 23 precision bits with 32 bits floats, sounds like it yeah.
I committed a fix yesterday. Vertex shader now has the default precision (highp 
float as mentioned in my comment), fragment shader float precision is 
explicitely set to mediump.

but for now our shaders still use default precision.

Original comment by remy.bou...@gmail.com on 21 Feb 2013 at 4:35

GoogleCodeExporter commented 9 years ago
OK, I am marking it as fixed then.
Using different precision in the shader is a separate issue and is not related 
to this one.

Original comment by ShadowIs...@gmail.com on 21 Feb 2013 at 4:47