Shader programs

OpenGL® ES is designed to take the data that describes a 3-D scene and manipulate it so that the scene is represented as a square grid of pixels on a 2-D display. The OpenGL ES pipeline refers to the stages that the 3-D scene data goes through to achieve a 3-D to 2-D transformation.

In versions of OpenGL ES prior to version 2.0, the operations that take place at each stage of the pipeline are fixed. You can set parameters that affect these fixed operations, but you cannot define new operations. For example, you can specify if your model should rotate and by how much. But you cannot define a new type of rotation that distorts the model as it rotates.

In OpenGL ES 2.0, you can define custom pipeline operations that act on vertices and fragments. You can define these operations in the GL shader language. You must define both a vertex shader program and a fragment shader program.

You create a shader object, add source code in GLSL that specifies the shader and then you compile the shader. The GLUtils library includes a glLoadShader() convenience method that you can use to do all of this in one call.

Best practice: Working with shader programs

Best practice

Description

Load shader programs from a file

Tutorials and sample code that demonstrate how to use OpenGL® ES shader programs often store the programs in string variables. Storing shader programs in string variables is useful when you are learning because it makes the code shorter and simpler. However, when you are writing production code, you should store your shader programs in files.

Check for shader program compile errors

Shader programs often have compile errors. You should always check for shader program compile errors and log any related error messages to help you debug problems. It is useful to log the messages to the event log or even to a modal dialog box.

The GLUtils.glLoadShader() method returns 0 if the shader failed to compile. The method accepts a string array parameter where any compiler error messages are stored. You should always check the return value and pass a string array to store error messages.

String[] infolog = new String[2];

int vertexShader = GLUtils.glLoadShader(gl,
                                        GL20.GL_VERTEX_SHADER,
                                        vertexShaderSource,
                                        infolog,
                                        0);

int fragShader   = GLUtils.glLoadShader(gl,
                                        GL20.GL_FRAGMENT_SHADER,
                                        fragShaderSource,
                                        infolog,
                                        1);
if (vertexShader == 0)
{
   throw new IllegalStateException("Vertex shader error: " 
                                   + infolog[0]);                             
}                 

if (fragShader == 0)
{
   throw new IllegalStateException("Fragment shader error: " 
                                   + infolog[1]);                             
}

Check shader program link status

Check the GL_LINK_STATUS of shader programs to make sure they linked without errors. If GL_LINK_STATUS == GL_FALSE, then there was a link error and you can retrieve the error message by calling GL20.glGetProgramInfoLog() before deleting the shader program.

int program = gl.glCreateProgram();
if(program == 0)
{
   throw new 
    IllegalStateException("Error creating shader program");
}

gl.glAttachShader(program,vertexShader);
gl.glAttachShader(program,fragmentShader);

gl.glLinkProgram(program);

int[] linked = new int[1];
gl.glGetProgramiv(program,GL20.GL_LINK_STATUS,linked,0);

if(linked[0] == GL20.GL_FALSE)
{
   String log = gl.glGetProgramInfoLog(program);
   gl.glDeleteProgram(program);
   throw new 
    IllegalStateException("Program link error: " + log);
}

Delete shader objects after linking a shader program

After a shader program is successfully linked, it does not have to remain in memory. You should delete vertex and fragment shader objects by calling GL20.glDeleteShader().

gl.glDeleteShader(vertexShader);
gl.glDeleteShader(fragShader);
Next topic: JSR 239 overview

Was this information helpful? Send us your comments.