Please send suggestions or corrections for this page to the author at sbuss@ucsd.edu.

This page describes the features of Modern OpenGL used in the SimpleDrawShaderMgr program. This is one of a series of programs illustrating features of Modern OpenGL. SimpleDrawShaderMgr is an adaptation of SimpleDrawModern (the first program in the series) to use the GlShaderMgr package to load, compile and link the shader program. Other than this, the program SimpleDrawShaderMgr is identical to SimpleDrawModern.

The previous program, SimpleDrawModern, hardcoded the source code for its shaders into C++ character arrays, in the source file ShaderMgrSDM.cpp. The new program,SimpleDrawShaderMgr, instead reads the shaders' source code from a file SimpleDraw.glsl. The advantage is that it makes it easier to maintain, and modify, the source for shaders. The disadvantage is that now an extra file of GLSL source code has to be distributed with the executable. However, GlShaderMgr allows multiple blocks of GLSL source code to be contained in a file, and hence only one GLSL source file is needed.

I. Loading, compiling and linking a single simple program shader

The following two lines are used in the routine my_setup_SceneData to load the source code for the shaders, compile the vertex shader and fragment shader, and link them into a shader program. The GlShaderMgr::CompileAndLinkAll compiles all the shaders and links them into a shader program: it returns the OpenGL handle (the OpenGL name) for the shader program. The rest of SimpleDrawShaderMgr is identical the old SimpleDrawModern.

    GlShaderMgr::LoadShaderSource("SimpleDraw.glsl");
    shaderProgram1 = GlShaderMgr::CompileAndLinkAll();

The file SimpleDraw.glsl contains in its entirety:

// Sets the position and color of a vertex.
//   This implementations just copies the position with no transformations.
//   It copies the color to "theColor" so that the fragment shader can access it.

#beginglsl vertexshader vertexShader_PosColorOnly
#version 330 core
layout (location = 0) in vec3 vertPos;	   // Position in attribute location 0
layout (location = 1) in vec3 vertColor;   // Color in attribute location 1
out vec3 theColor;					       // Output a color to the fragment shader
void main()
{
   gl_Position = vec4(vertPos.x, vertPos.y, vertPos.z, 1.0);
   theColor = vertColor;
}
#endglsl

// Set a general color using a fragment shader. (A "fragment" is a "pixel".)
//    The color value is passed in, obtained from the color(s) on the vertice(s).
//    Color values range from 0.0 to 1.0.
//    First three values are Red/Green/Blue (RGB).
//    Fourth color value (alpha) is 1.0, meaning there is no transparency.

#beginglsl FragmentShader fragmentShader_ColorOnly
#version 330 core
in vec3 theColor;		// Color value came from the vertex shader (smoothed) 
out vec4 FragColor;	    // Color that will be used for the fragment
void main()
{
   FragColor = vec4(theColor, 1.0f);   // Add alpha value of 1.0.
}
#endglsl

The file contains two shaders, a vertex shader and a fragment shader. The beginning and end of a shader is indicated by the lines #beginglsl and #endglsl. A #beginglsl line specifies the type of the shader, either a vertex shader or a fragment shader in this case; it also gives the name of the shader. Thus the line,

#beginglsl vertexshader vertexShader_PosColorOnly

starts a block of code which is (the main part of) a vertex shader named vertexShader_PosColorOnly.

Lines outside the scope of a #beginglsl - #endglsl pair are ignored: they are treated as just comments: the fact that they start with "//" is irrelevant.

II. Alternate methods for compiling and linking a shader program

The single call to GlShaderMgr::CompileAndLinkAll was possible since there was only a single shader program, and each shader consisted of a single block of code. When there is more than one shader program, a more general way to do the compilation and linking is:

    GlShaderMgr::LoadShaderSource("SimpleDraw.glsl");
    shaderProgram1 = GlShaderMgr::CompileAndLinkProgram("vertexShader_PosColorOnly", "fragmentShader_ColorOnly");
	
	// Free up shader compilation resources that are no longer needed.
    GlShaderMgr::FinalizeCompileAndLink();

This compiles the two named shaders, and links them together into a shader program. The call to GlShaderMgr::FinalizeCompileAndLink frees up the memory used for the shaders' course code, and deletes the no-longer needed compiled shaders. This does not affect the usability of the shader program named by shaderProgram1.

In more complicated situations, it might be desirable to have finer control over the compilation and linkage. For instance, another way to compile and link the shader program is:

    GlShaderMgr::LoadShaderSource("SimpleDraw.glsl");
    unsigned int vertexShader = GlShaderMgr::CompileShader("vertexShader_PosColorOnly");
    unsigned int fragmentShader = GlShaderMgr::CompileShader("fragmentShader_ColorOnly");
    unsigned int shaders[2] = { vertexShader, fragmentShader };
    shaderProgram1 = GlShaderMgr::LinkShaderProgram(2, shaders);
	
	// Free up shader compilation resources that are no longer needed.
    GlShaderMgr::FinalizeCompileAndLink();