GLSL ES shader precision qualifier

Table of contents

Preface

Three types of precision supported by WebGL

Default precision for data types

float type has no default precision 

preprocessing directives

There are three preprocessing instructions commonly used in GLSL ES.

Predefined built-in macros


Preface

GLSL ES has newly introduced precision qualifiers to help shader programs improve operating efficiency and reduce memory expenses. As the name suggests, the precision qualifier is used to indicate the precision (number of bits) of each type of data. In short, high-precision programs require greater overhead (including larger memory and longer computation time), while low-precision programs require much less overhead. Using precision qualifiers, you can finely control the balance between effects and performance of your program. However, the precision qualifier is optional, and if you're not sure, you can use the following modest default:

Since WebGL is based on OpenGL ES 2.0, WebGL programs may eventually run on a variety of hardware platforms. There are definitely situations where it is necessary to run programs at low precision to improve memory usage efficiency, reduce performance overhead, and more importantly, reduce energy consumption and extend the battery life of mobile devices.

Note that at low precision, the running results of WebGL programs will be rough or inaccurate, and you must balance program effects and performance.

Three types of precision supported by WebGL

As shown in the figure below, the WebGL program supports three precisions, and the qualifiers are highp (high precision) , mediump (medium precision) and lowp (low precision)

There are two further points worth noting. First, in some WebGL environments, the fragment shader may not support highp precision . The method of checking (whether it supports it) will be discussed later (see below: Preprocessing instructions) ; secondly, the numerical range and precision are actually related to System environment related, you can use gl.getShaderPrecisionFormat() to check.

Here are a few examples of declaring variable precision:

Declaring the precision for each variable is tedious. We can also use the keyword precision to declare the default precision of the shader. This line of code must be at the top of the vertex shader or fragment shader. Its format is as follows:

This code indicates that in the shader, the default precision of a certain type of variable is specified by the precision qualifier. In other words, the precision of all subsequent variables of this type that are not modified with precision qualifiers is the default precision. for example:

 

The above code indicates that all variables of float type and related vec2 and mat3 are medium-precision, and all integer variables are high-precision. For example, the four components of the vec4 type variable are all medium precision. 

For some types, the shader has implemented default precision. Only the float type in the fragment shader does not have a default precision. As shown in the table.

Default precision for data types

float type has no default precision 

The fact is that the float type in the fragment shader does not have a default precision, we need to specify it manually. If we do not limit the precision of the float type in the fragment shader, it will cause the following compilation error:

 

Whether WebGL supports highp precision in fragment shaders depends on the specific device. If supported, the shader will define the built-in macro GL_FRAGMENT_PRECISION_HIGH. 

preprocessing directives

GLSL ES supports preprocessing directives. Preprocessing instructions are used to preprocess the code before actual compilation, and they all start with a pound sign (#). example:

This code checks whether the GL_ES macro has been defined, and if so, executes the part between #ifdef and #endif.

There are three preprocessing instructions commonly used in GLSL ES.

You can use the #define directive to define macros.

You can undefine a macro using the #undef directive:

You can use the #else directive with #ifdef (just like else in an if statement in JavaScript), for example: 

The name of the macro can be arbitrary, as long as it is not the same as the name of the predefined built-in macro.

Predefined built-in macros

Therefore, we can use macros to limit precision like this: (Determine whether the current WebGL environment supports high precision. If there is a predefined GL_FRAGMENT_PRECISION_HIGH built-in macro, the floating point type is high precision) 

 

Guess you like

Origin blog.csdn.net/dabaooooq/article/details/132794417