Francesco Guastella

aka romeoxbm

Uniform handling in OpenGL (pt. 1)

Download in PDF format

Handling uniform variables can be a crucial aspect for a 3D application using opengl.
There are several tutorials about this topic, many of them can be easily found in internet, but one of them surely whetted my wits (let me take this occasion to suggest you to read it) and it can be found in Game Engine Gems 2.
The reason why you are reading this article is quite simple: all of these tutorials left in me an huge dissatisfaction when they proposed their implementation for the Uniform class.
In fact, nobody approached the issue of handling different data types we will surely have to deal with, just describing how we could use float variables only.
So the goal of these lines is to take care of this dissatisfaction, proposing a complete implementation of an uniform handling system, turning our attention to common problems (and related solutions) that could show up when trying to create an Uniform class able to handle different data types and components number (think for instance about the vec3 type, which is essentially a set of three float values).
The principle behind this system is pretty simple and efficient: once we create our shader program, we retrieve all the uniform variables and we make sure that every uniform send its value to the graphics card only if it has been modified during the execution.
Doing this way, we can avoid redundant calls and reach an high abstraction level that allow us to interact with our GPU programs in a very simple manner. Let’s see an example of what we are trying to achieve:

Let’s start writing what we need in the class ShaderProgram, which represent the main subject of this article (we will talk about the Uniform class in the next one).
We will give to ShaderProgram the following look:

First of all, we need to know exactly how many uniforms has our program, and we will retrieve this information by using activeUniformCount and _getUniforms methods; these are the proposed implementations for these two methods:

The _getUniforms method use gl::GetProgramResourceiv to get informations about uniform’s name, its type (gl::FLOAT, gl::DOUBLE, etc.) and the location, and finally create an object that will be stored inside an std::map that use string keys.
We will talk about the _createUniform method implementation in the next article.
Let’s take a look instead to the uniformByName method, which is pretty easy:

Up to now, we created all the tools that enable us to get all the uniform variables from our shader program.
The next essential step is to ensure, as we said above, that every uniform variable value is sent to the GPU only if it received updates; we get this by adding a vector of dirty uniforms in ShaderProgram, and we will use this vector in upload, a method responsible for sending data to our GPU which looks like:

To get ShaderProgram aware of updated uniforms, and then populate the _dirtyUniforms vector, we have to notify every change to ShaderProgram through Uniform‘s set method.
Suppose for an instant that the Uniform class handles float values; here it is how we could close our circle, supposing furthermore that Uniform::set has the following implementation:

Where _owner is a pointer to ShaderProgram and _value is a Uniform member of type float.
The ShaderProgram‘s notifyDirty method, obviously, will take care of inserting the new object into _dirtyUniforms.

To this point, we described how we can write a class called ShaderProgram that handles uniform variables in a simple manner, avoiding redundant calls by using a simple mechanism.
In the next article we will discuss the Uniform class, showing how it is possible to handle different data types and components number (do not forget we often deal with vectors of two, three or four components, quaternions and matrices).

Download in PDF format

Tags: ,

Leave a Reply

Switch to our mobile site