In OpenGL ES 2.0 / GLSL, where do you need precision specifiers?

Jessy picture Jessy · Mar 20, 2011 · Viewed 54k times · Source

Does the variable that you're stuffing values into dictate what precision you're working with, to the right of the equals sign?

For example, is there any difference, of meaning, to the precision specifier here:

gl_FragColor = lowp vec4(1);

Here's another example:

lowp float floaty = 1. * 2.;
floaty = lowp 1. * lowp 2.;

And if you take some floats, and create a vector or matrix from them, will that vector or matrix take on the precision of the values you stuff it with, or will those values transform into another precision level?

I think optimizing this would best answer the question:

dot(gl_LightSource[0].position.xyz, gl_NormalMatrix * gl_Normal)

I mean, does it need to go this far, if you want it as fast as possible, or is some of it useless?

lowp dot(lowp gl_LightSource[0].position.xyz, lowp gl_NormalMatrix * lowp gl_Normal)

I know you can define the default precision for float, and that this supposedly is used for vectors and matrices afterwards. Assume for the purpose of education, that we had defined this previously:

precision highp float;

Answer

Mikola picture Mikola · Jun 13, 2011
  1. You don't need precision specifiers on constants/literals since those get compile time evaluated to whatever they are being assigned to.

  2. In vertex shaders, the following precisions are declared by default: (4.5.3 Default Precision Qualifiers)

    precision highp float;
    precision highp int;
    precision lowp sampler2D;
    precision lowp samplerCube;
    

    And in fragment shaders you get:

    precision mediump int;
    precision lowp sampler2D;
    precision lowp samplerCube;
    

    This means that if you declare a float in a fragment shader, you have to say whether it is a lowp or a mediump. The default float/int precisions also extend to matrices/vectors.

  3. highp is only supported on systems that have the GL_FRAGMENT_PRECISION_HIGH macro defined to 1; on the rest you'll get a compiler error. (4.5.4 Available Precision Qualifiers)

  4. The rule for precision in an expression is that they get cast automatically to the type of the assignment / parameter they are bound to. So for your dot, it would use the precision of the input types by default and the additional lowp's are unnecessary (and syntactically incorrect). If you want to down-cast a type to a lower precision, the only way to do it is to explicitly assign it to a lower precision.

These answers are all from the Khronos GLSL spec, which you can find here (relevant sections are 4.5.2 and 4.5.3): http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf