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.
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.
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();