Book Image

OpenGL ES 3.0 Cookbook

By : Parminder Singh
Book Image

OpenGL ES 3.0 Cookbook

By: Parminder Singh

Overview of this book

<p>"Write once, use anywhere" is truly the power behind OpenGL ES and has made it an embedded industry standard. The library provides cutting-edge, easy-to-use features to build a wide range of applications in the gaming, simulation, augmented-reality, image-processing, and geospatial domains.</p> <p>The book starts by providing you with all the necessary OpenGL ES 3.0 setup guidelines on iOS and Android platforms. You'll go on to master the fundamentals of modern 3D graphics, such as drawing APIs, transformations, buffer objects, the model-view-project analogy, and much more. The book goes on to deal with advanced topics and offers a wide range of recipes on the light shading, real-time rendering techniques with static and procedure textures to create stunning visualizations and runtime effects.</p>
Table of Contents (21 chapters)
OpenGL ES 3.0 Cookbook
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Programming shaders in OpenGL ES shading language 3.0


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.

Getting ready

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.

How to do it...

Here are the sample codes for vertex and fragment shaders:

  1. 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;
    }
  2. 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;
    };

How it works...

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.

There's more…

As mentioned there are three types of precision qualifiers, the following table describes these:

Qualifier

Description

highp

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.

lowp

These variables may typically be used to store high dynamic range colors and low precision geometry.

mediump

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.

See also

  • Loading and compiling a shader program

  • Using the per-vertex attribute to send data to a shader

  • Using uniform variables to send data to a shader