Floating Point Data Types

Unless you are dealing with massive data sets for which CPU and/or GPU memory (and possibly even disk storage) is a concern – perhaps along with data transfer rates among these devices – I generally advocate using double for all floating point computation and variables. Performance is oftentimes less of an issue than is the increased precision you obtain.

However:

  1. All versions of GLSL prior to those packaged with OpenGL 4 support only single precision float. (Some pre-version 4 implementations may support double to various extents as an extension.)
  2. Starting with OpenGL 4 and GLSL 400, the GLSL language supports both float and double.
  3. Independent of OpenGL and GLSL versions, not all GPUs support double arithmetic.

Notice that all GLSL programs should begin with a #version declaration that makes explicit which version of GLSL is assumed. It is permissible to use a GLSL shader program at a lower level than that supported by the current OpenGL version. For example, a GLSL program at version 330 (associated with OpenGL 3.3) can be used in an OpenGL 4.2 program.

You must be aware of targeted GPUs as well as targeted versions of GLSL when declaring and using floating point data. As you saw in "Hello OpenGL", routines like glVertexAttribPointer that manage access to buffers sent to the server must be told whether single or double precision values were sent. You also need to declare variables appropriately in the GLSL program (not only float versus double but also other built-in vector and matrix types such as vec3 (a 3-tuple of float) versus dvec3 (a 3-tuple of double), etc.).

All the GLSL programs currently on this site assume single precision floating point data are sent to the GLSL program from the client. The CPU client code frequently uses double precision in different contexts for different reasons. If needed, explicit conversions to float are performed before sending data to the GPU.

Other GLSL Built-in Data Types

In addition to the conventional C/C++ primitive types, GLSL also defines several additional data types. We will see many of them as we progress through the course. Here is a small initial sample and some notes on their use. (See also "GLSL Overview" in the Developer Notes section.)

These built-in data types (vec2, et al.) are of course only built into GLSL. In order to make connections between CPU and GPU data objects clearer, we will often use something like the following in our CPU-side C++ code when allocating, initializing, and transferring data from the CPU to the GPU:

typedef float vec2[2];
vec2* verts = new vec2[N];
…
for (int i=0 ; i<N ; i++)
{
    …
    verts[i][0] = the-x-coordinate;
    verts[i][1] = the-y-coordinate;
    …
}
…
glBufferData(GL_ARRAY_BUFFER, N*sizeof(vec2), verts, GL_STATIC_DRAW);
delete [] verts;
…

BUT NOTE:

You must not confuse a C++ identifier declared via a typedef like this as being a class object. That is, while the following are valid in GLSL code, they are NOT VALID in C++ code:

vec2 somePoint = vec2(1.2, -3.1);
vec3 another = vec3(0, 1.2, 3);
vec3 myPnt = another; // myPnt is an independent copy of another

In C++ code using typedefs like that shown above, variables like these are arrays, hence can only be initialized and used as such. Moreover, arrays cannot be copied as in the third example in C++.