Set glsl
This section describes how to configure glsl in OpenGL. Assume that you have written vertex shader and pixel shader. If you are not ready, you can obtain the relevant content from the following URL:
Http://www.3dshaders.com/home/
Http://www.opengl.org/sdk/tools/ShaderDesigner/
Http://developer.amd.com/archive/gpu/rendermonkey/pages/default.aspx
In OpenGL, the shader of glsl uses a process similar to the C language. Each shader is similar to a C Module. First, you need to compile it separately (compile), and then a set of compiled shader connections (link) into a complete program.
The ARB extension will be ignored here and only the opengl2.0 code will be listed. We recommend that you use the glew Library:
Http://glew.sourceforge.net/
The following code checks OpenGL 2.0 for availability:
#include <GL/glew.h>#include <GL/glut.h>void main(int argc, char **argv){ glutInit(&argc, argv); ... glewInit(); if (glewIsSupported("GL_VERSION_2_0")) printf("Ready for OpenGL 2.0\n"); else { printf("OpenGL 2.0 not supported\n"); exit(1); } setShaders(); glutMainLoop();}
The necessary steps for creating a shader are displayed. The detailed usage of the function is described below:
Create a shader
The steps for creating a shader are shown:
First, create an object as the shader container. This creation function will return the Container Handle.
Gluint glcreateshader (glenum shadertype); parameter: · shadertype-gl_vertex_shader or gl_fragment_shader.
You can create many shader, but remember that all vertex shader can only have one main function, and the shader of all pixels is the same.
Next, add the source code. The source code of the shader is a string array. The syntax is as follows:
Void glshadersource (gluint shader, int numofstrings, const char ** strings, int * lenofstrings); parameter: · shader-the handler to the shader. · numofstrings-the number of strings in the array. · strings-the array of strings. · lenofstrings-an array with the length of each string, or null, meaning that the strings are NULL terminated.
Finally, compile the shader:
Void glcompileshader (gluint shader); parameter: • shader-the handler to the shader.
Create a program
Shows the steps to obtain a shader program that can be run:
First, create an object as the program container. This function returns the Container Handle.
GLuint glCreateProgram(void);
You can create any number of programs. During rendering, you can switch between different programs, or even return a fixed function pipeline at a frame. For example, you want to use the shader to draw a cup and then return to the fixed function to generate a cube environment map to display the background.
The shader compiled in the previous section will be appended to the created program. The method is as follows:
Void glattachshader (gluint program, gluint shader); parameter: · Program-the handler to the program. · shader-the handler to the shader you want to attach.
If there are vertex shader and segment shader at the same time, you need to append them to the program. You can append multiple shader of the same type (vertex or pixel) to a program, just as a C program can have multiple modules, but they can only have one main function.
You can also append a shader to multiple programs. For example, you want to use the same shader in different programs.
The last step is to connect the program. The method is as follows:
Void gllinkprogram (gluint program); parameter: · Program-the handler to the program.
After the connection operation, the source code of shader can be modified and re-compiled without affecting the entire program.
After the program is connected, you can call gluseprogram to use the program. Each program is assigned a handle. You can connect multiple programs for use in advance.
Void gluseprogram (gluint prog); parameter: · prog-the handler to the program you want to use, or zero to return to fixed functionality.
When a program is used, if it is connected again, it will be automatically replaced and put into use, so there is no need to call the above function again. If the parameter is 0, a fixed function pipeline is used.
Example
The following code contains all the steps described above. The parameters P, f, and V are global gluint variables.
void setShaders(){ char *vs,*fs; v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); vs = textFileRead("toon.vert"); fs = textFileRead("toon.frag"); const char *vv = vs; const char *ff = fs; glShaderSource(v, 1, &vv, NULL); glShaderSource(f, 1, &ff, NULL); free(vs);free(fs); glCompileShader(v); glCompileShader(f); p = glCreateProgram(); glAttachShader(p, v); glAttachShader(p, f); glLinkProgram(p); glUseProgram(p);}
The complete example of glut is as follows:
Http://lighthouse3d.com/wptest/wp-content/uploads/2011/03/glutglsl_2.0.zip
The complete example contains the shader code and text file reader.
Error Handling
Debugging shader is very difficult. There is no such thing as printf at present, although there may be development tools with debugging functions in the future.
The status of the compilation phase can be obtained using the following functions:
Void glgetshaderiv (gluint object, glenum type, int * PARAM); parameter: · object-the handler to the object. either a shader or a program-type-gl_compile_status. · param-the return value, gl_true if OK, gl_false otherwise.
The connection status can be obtained using the following functions:
Void glgetprogramiv (gluint object, glenum type, int * PARAM); parameter: · object-the handler to the object. either a shader or a program-type-gl_link_status. · param-the return value, gl_true if OK, gl_false otherwise.
If an error occurs, you need to find more information from infolog. This log stores information about the last operation, such as warnings and errors during compilation and various problems that occur during connection. This log even tells you whether the hardware supports your shader. Unfortunately, infolog does not have a specification, so different drivers/hardware may generate different log information.
To obtain logs of a specific shader or program, you can use the following program:
Void glgetshaderinfolog (gluint object, int maxlen, int * Len, char * log); void glgetprograminfolog (gluint object, int maxlen, int * Len, char * log); parameter: · object-the handler to the object. either a shader or a program · maxlen-the maximum number of chars to retrieve from the infolog. · len-returns the actual length of the retrieved infolog. · log-the log itself.
The glsl specification must be improved here: you must know the length of the received infolog. To find the exact value, use the following function:
Void glgetshaderiv (gluint object, glenum type, int * PARAM); void glgetprogramiv (gluint object, glenum type, int * PARAM); parameter: · object-the handler to the object. either a shader or a program-type-gl_info_log_length. · param-the return value, the length of the infolog.
The following functions can be used to print infolog content:
void printShaderInfoLog(GLuint obj){ int infologLength = 0; int charsWritten = 0; char *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength); if (infologLength > 0) { infoLog = (char *)malloc(infologLength); glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog); printf("%s\n",infoLog); free(infoLog); }} void printProgramInfoLog(GLuint obj){ int infologLength = 0; int charsWritten = 0; char *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength); if (infologLength > 0) { infoLog = (char *)malloc(infologLength); glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog); printf("%s\n",infoLog); free(infoLog); }}
Clear
The preceding section describes how to append a shader to a program. The call here is to separate the shader from the program:
Void gldetachshader (gluint program, gluint shader); parameter: · Program-the Program to detach from. · shader-the shader to detach.
Note: Only the shader that has not been attached to any program can be deleted. The call to delete shader and program is as follows:
Void gldeleteshader (gluint ID); void gldeleteprogram (gluint ID); parameter: · ID-The handid of the shader or program to delete.
If a shader is attached to a program, the shader cannot be deleted and can only be marked as deleted. After the shader is separated from all programs, it will be finally deleted.