This tutorial shows the usage of lazily-initialized uniforms. Unlike regular Uniforms which require the program, which they reference to be compiled and linked before the Uniform
is constructed, lazy uniforms only require that the Program instance exists - it does not have to be built yet. LazyUniforms postpone the initialization until the value of the uniform is set or some other operation is executed.
If you are not familiar with the basics of OGLplus, it is recommended that you read the RGB triangle first for a more detailed introduction. You can also see the Basic usage with GLUT and GLEW for a complete standalone example including the code responsible for window initialization, OpenGL initialization and event handling.
The new things that this tutorial covers are:
For a full working code see the oglplus/004_rect.cpp
file in the example directory.
Like in the previous tutorials we first include the header that makes sure that the OpenGL symbols are defined and the one that includes everything from OGLplus,
and also the header declaring the base class for OGLplus examples.
Just like the other examples that come with the library this one is also implemented inside of the oglplus
namespace.
As before, the example code is encapsulated in the RectangleExample
class which is derived from oglplus::Example
.
Most of the member variables are the same as in the previous tutorials. There is an instance of the oglplus::Context
class wrapping the current context functions:
The following line is a little different from the previous tutorials. We could have used oglplus::VertexShader
and a oglplus::FragmentShader
types, but sometimes it is necessary to decide what kind of shader we want at run-time (based for example on some input data). This tutorial is not one of those time, but we take this opportunity to show the usage of untyped shaders:
next there is a oglplus::Program
a oglplus::VertexArray
object managing the vertex data for the rendered rectangle stored in oglplus::Buffer
.
Now we declare three oglplus::LazyUniform variables which set the values of the RedCenter
, BlueCender
and GreenCenter
uniform variables in the fragment shader below. The uniforms in the shader have the vec2
type - hence the Vec2f
template parameter for LazyUniform
.
The public interface again consists of a constructor and a couple of member functions.
The constructor constructs the vertex and fragment shaders, using the oglplus::ShaderType:
The following line is technically not necessary, but it is here to remind us that the program must be constructed before we try to initialize the uniforms:
Now we can initialize the uniforms, the constructor takes a reference to a Program and the identifier of the variable that we wish to reference by the LazyUniform:
Now we can set the source of the vertex shader. There is one new thing here - we are wrapping the source string in the StrLit
class to tell the shader that it is initialized from a literal (which allows OGLplus and the compiler to do some optimizations):
The vertex shader is complete and can be compiled.
The fragment shader is similar to the one from the previous tutorials. It has one input variable - the vertex coordinate that will be used in the newton fractal computations.
Also note the three uniform variables, that specify the centers of the red, green and blue 'lights' on the surface of the rendered rectangle:
As before, the output of the shader is a vec4 representing the color of the fragment.
Then we calculate the distances of the fragment from the centers of the three 'lights' stored in the uniforms, store them in a vector and then use the values to colorize the fragment.
We can now compile the fragment shader source code, attach both shaders to the shading program and try to link and use it.
Now we can start to specify the data for the individual vertex attributes of the rectangle we're going to render. The first step as before is to bind the vertex array object managing the vertex data.
Again, since this is a simple example the coordinates are hardcoded.
We bind the VBO for vertex positions to the ARRAY_BUFFER
target.
The data are uploaded from client's memory to the server's memory by using the Buffer
's Data
static function.
Then we use a oglplus::VertexAttribArray object referencing the Position
input variable in the prog
program, to tell OpenGL about the structure of the data in the currently bound VBO and to enable this vertex attribute.
Now we can specify the values of the uniform variables. Note that because we used lazily-initialized uniforms, the uniform variables in the compiled program are referenced only now. We use the Set
function with two parameters since the underlying uniform type is Vec2f
.
The rest of the tutorial is basically the same as before. We finish the constructor and we implement the Reshape
and Render
member functions and the makeExample
function for creating an instance of the RectangleExample
class.