OpenGL ES shading language 3.0 (also called as GLSL) is a C-like language that allows us to writes shaders for programmable processors in the OpenGL ES processing pipeline. Shaders are the small programs that run on the GPU in parallel. Without these programs, it is impossible to write OpenGL ES 3.0 programs.
OpenGL ES 3.0 supports two type of shaders: vertex shader and fragment shader. Each shader has specific responsibilities. For example, the vertex shader is used to process geometric vertices; however, the fragment shader processes the pixels or fragment color information. More specially, the vertex shader processes the vertex information by applying 2D/3D transformation. The output of the vertex shader goes to the rasterizer where the fragments are produced. The fragments are processed by the fragment shader, which is responsible for coloring them.
The order of execution of the shaders is fixed; the vertex shader is always executed first, followed by the fragment shader. Each shader can share its processed data with the next stage in the pipeline. The GLSL facilitates user-defined variables such as C language; these variables are used for input and output purposes. There are also inbuilt variables that track the states in the shaders to make decisions while processing data in these shaders. For example, the fragment shader provides a state where the incoming fragment can be tested to see if it belongs to the front face or back face of a polygon.
There are two types of processors in the OpenGL ES 3.0 processing pipeline to execute vertex shader and fragment shader executables; it is called programmable processing unit:
Vertex processor: The vertex processor is a programmable unit that operates on the incoming vertices and related data. It uses the vertex shader executable and run it on the vertex processor. The vertex shader needs to be programmed, compiled, and linked first in order to generate an executable, which can then be run on the vertex processor.
Fragment processor: This is another programmable unit in the OpenGL ES pipeline that operates on fragments and related data. The fragment processor uses the fragment shader executable to process fragment or pixel data. The fragment processor is responsible for calculating colors of the fragment. They cannot change the position of the fragments. They also cannot access neighboring fragments. However, they can discard the pixels. The computed color values from this shader are used to update the framebuffer memory and texture memory.
Here are the sample codes for vertex and fragment shaders:
Program the following vertex shader and store it into the
vertexShader
character type array variable:#version 300 es in vec4 VertexPosition; in vec4 VertexColor; uniform float RadianAngle; out vec4 TriangleColor; mat2 rotation = mat2(cos(RadianAngle),sin(RadianAngle), -sin(RadianAngle),cos(RadianAngle)); void main() { gl_Position = mat4(rotation)*VertexPosition; TriangleColor = VertexColor; }
Program the following fragment shader and store it into another character array type variable called
fragmentShader
:#version 300 es precision mediump float; in vec4 TriangleColor; out vec4 FragColor; void main() { FragColor = TriangleColor; };
Like most of the languages, the shader program also starts its control from the main()
function. In both shader programs, the first line, #version 300 es
, specifies the GLES shading language version number, which is 3.0 in the present case. The vertex shader receives a per-vertex input variable VertexPosition
. The data type of this variable is vec4
, which is one of the inbuilt data types provided by OpenGL ES Shading Language. The in
keyword in the beginning of the variable specifies that it is an incoming variable and it receives some data outside the scope of our current shader program. Similarly, the out
keyword specifies that the variable is used to send some data value to the next stage of the shader. Similarly, the color information data is received in VertexColor
. This color information is passed to TriangleColor
, which sends this information to the fragment shader, and is the next stage of the processing pipeline.
The RadianAngle
is a uniform type of variable that contains the rotation angle. This angle is used to calculate rotation matrix into rotation
. Refer to following See also section to get reference for the per-vertex
attribute and uniform
variables.
The input values received by VertexPosition
are multiplied using the rotation matrix, which will rotate the geometry of our triangle. This value is assigned to gl_Position
. The gl_Position
is an inbuilt variable of the vertex shader. This variable is supposed to write the vertex position in the homogeneous form. This value can be used by any of the fixed functionality stages, such as primitive assembly, rasterization, culling, and so on. Refer to the The fixed function and programmable pipeline architecture recipe in Appendix, Supplementary Information on OpenGL ES 3.0, for more information on the fixed stages.
In the fragment shader, the precision keyword specifies the default precision of all floating types (and aggregates, such as mat4
and vec4
) to be mediump
. The acceptable values of such declared types need to fall within the range specified by the declared precision. OpenGL ES Shading Language supports three types of the precision: lowp
, mediump
and highp
. Specifying the precision in the fragment shader is compulsory. However, for vertex, if the precision is not specified, it is consider to be highest (highp
).
FragColor
is an out
variable, which sends the calculated color values for each fragment to the next stage. It accepts the value in the RGBA color format.
As mentioned there are three types of precision qualifiers, the following table describes these:
Qualifier |
Description |
---|---|
|
These variables provide the maximum range and precision. But they can cause operations to run more slowly on some implementations; generally, vertices have high precision. |
|
These variables may typically be used to store high dynamic range colors and low precision geometry. |
|
These variables may typically be used to store 8-bit color values. |
The range and precision of these precision qualifiers are shown here:
The preceding image is taken from page 48 of https://www.khronos.org/registry/gles/specs/3.0/GLSL_ES_Specification_3.00.3.pdf.
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.