312 CHAPTER 10: OpenGL ES 2, Shaders, and...^
return YES;
}
When you get away from all of the error handling code, the process boils down to
creating a shader, passing in the source, and compiling.
In the argument list of line 1, an address is passed to receive the newly
generated shader’s. handle. A type value is also supplied, which can
be either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER. And finally a file
name is specified. You don’t need to supply a shader from a file,
because others may actually specify the shader as static strings
defined inside the body of the code.
In line 2, glCreateShader() generates an empty shader object and
returns its handle.
Line 3 passes the source of the shader to the newly created object,
because its real job is to contain the text strings used to define the
shader.
Next we compile the thing in line 4.
Now we should check the compilation status. Since there is no means
to debug shaders when on the GPU, a nice error management system
has been provided that can send back fairly detailed strings to the
calling program. Line 5 gets the length of the string, while 6 gets the
actual contents. For example, in Shader.vsh, I supplied a variable that
was never defined and received the following:
ERROR: 0:19: Use of undeclared identifier 'normalX'
But instead of using a string to determine what to do, you can also get
a numerical error of either GL_TRUE if the compile was actually
successful or GL_FALSE if otherwise, as shown in line 7. And if not,
delete the shader, as in line 8.
The next step in the process is to link the program, as shown in Listing 10-2.
glLinkProgram() is the only call of any significance, with the rest being error handling.
Listing 10-2. Linking the Newly Created Shader Program
- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
#if defined(DEBUG)
GLint logLength;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);