Chapter 5: Appendix
Chapter 5: Appendix
Course
Chapter 5 Appendix
By
Jacobo Rodriguez Villar
[email protected]
GL_ARB_vertex_shader
GL_ARB_fragment_shader
GL_ARB_shader_objects
GL_ARB_shading_language
If the card does support GLSL, you can attempt to load/use the shader in the
following way:
Load the source string into your shader using the glShaderSourceARB
call:
For example, to use a vertex shader called generic.vert (the file extension is
not important), you would initialize it using the following code:
shader = _open(filename,_O_RDONLY);
if(shader == ENOENT)
size = -1;
{
FILE *source = fopen("generic.vert","rb");
size_t size = ProgramSize("generic.vert");
GLcharARB *programSource = (GLcharARB *)malloc(size*sizeof(GLcharARB));
fread(m_programSource,m_size,1,source);
fclose(source);
GLhandleARB vertexShader = glCreateShaderObjectARB(Glenum shaderType);
glShaderSourceARB(vertexShader, 1,(const GLcharARB **)&programSource,NULL);
free(programSource);
glCompileShaderARB(vertexShader);
}
The shader is now compiled and ready to be attached to a program object (the
executable unit that is a placeholder for compiled shaders). However, you may
want to know the compilation result, as well as warning/error messages (if any).
If the compiled variable returns false the shader will not compile due to errors
(ill-formed data, resource issues, etc.). You may gain more information by
retrieving the compilation log, but you must first find its length in order to
allocate enough space for it.
We can now define an executable unit by creating and compiling the program
object. This process involves linking global variables, varyings, etc.
GLhandleARB glCreateProgramObjectARB(void)
Once created and compiled, the vertex and fragment shaders must be inserted'
into the program object (they can be inserted into multiple program objects).
This can be achieved using the glAttachObjectARB call:
When the shaders are attached, you can link your program and leave it ready to
be used:
You can also query the link status and information log:
glLinkProgramARB(program);
glGetObjectParameterivARB(m_program,GL_OBJECT_LINK_STATUS_ARB,&resul);
glGetObjectParameterivARB(m_program,GL_OBJECT_INFO_LOG_LENGTH_ARB,&length);
glGetInfoLogARB(program,length,&laux,infoLog);
We now need to activate the program by making it part of the current state,
which can be done using:
glUseProgramObjectARB(program);
// Render some stuff, with glVertex, glDrawElements...
glUseProgramObjectARB(0); //back to fixed function pipeline
Using Uniforms
Using textures involves passing both the texture unit (not the texture object)
number to the shader and the correct binding of the texture to that unit.
You can find out the maximum number of textures a program object can support
by querying the GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB define
with glGetInteger (which, once known, can simply activate each texture unit
and bind the texture to it) (glEnable is not required here):
Every time the glNormal, glTexCoord, and glColor functions are called, you
send pre-defined vertex attributes to the vertex shader. Vertex arrays (like
glTexCoordPointer and glNormalPointer) can be used as well.
We will now look at some generic attributes which work in much the same way,
but are more flexible, as you can assign descriptive names or complex types
(like mat4 instead of normal vec types).
Vertex attributes must be bound to a free slot, which can be obtained via the
OpenGL API, but this the program must be linked or else it will not work (as it is
the link operation that decides which slots are free/not free):
For example:
This method will always retrieve a free slot, unless they are all occupied (we
can force slots with the glBindAttribLocationARB function, but it's better to
ask OpenGL for a free one).
Once a slot has been established, we can then send the attributes to OpenGL
just like standard attributes and vertices. There are two ways to do this:
immediate mode and vertex arrays.
Immediate mode:
Using glVertexAttrib*ARB between a glBegin/glEnd pairing, like glNormal or
glTexCoord :
glActiveTextureARB(GL_TEXTURE5_ARB);
glClientActiveTextureARB(GL_TEXTURE5_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3,GL_FLOAT,0,geometry);
glNormalPointer(GL_FLOAT,0,normals);
//draw stuff
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
To use generic vertex attribute arrays, a location is needed, which allows you to
setup your arrays easily:
glActiveTextureARB(GL_TEXTURE5_ARB);
glClientActiveTextureARB(GL_TEXTURE5_ARB);
glEnableVertexAttribArrayARB(location);
glVertexAttribPointerARB(location,size,type,false,0,myarray);
//draw some stuff
glDisableVertexAttribArrayARB(location);
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
Though this example may not be very good (as it assumes vertex attributes
only, without vertices, so no drawing is actually performed), the objective is to
show how to correctly setup a generic vertex attribute array.
Though Shader Designer has a series of default meshes, you may wish to
import your own geometry. This can be done using the Flexporter
(http://www.codercorner.com/Flexporter.htm) a plug-in manager for 3DSMax5,
with the Shader Designers export plugin.
This export plugin allows you to export an entire scene (without animations) to a
GSD (Shader Designer mesh format) file. However, there are a couple of items
to take into consideration before exporting any data:
OpenGL Shading Language API man pages, GLSL examples and resources:
http://developer.3dlabs.com