Skip to content

JOML and modern OpenGL

Kai Burjack edited this page Jun 3, 2015 · 11 revisions

If you want to use modern OpenGL without OpenGL's matrix stack functions glTranslate, glRotate, glPushMatrix, etc., you are probably wondering, how you would go about building the transformation matrices now?

We have the answer for this: JOML to the rescue! :)

Rotate, scale and translate

Three of the most basic affine transformations are translation, scaling and rotation. Using these three building blocks you can create any non-perspective transformation you want to move your objects around in the scene.

In the following example, we will show you how to use JOML for that. First we will build a transformation matrix allowing us to rotate any object 90 degrees about the Y-axis. Then it should scale the object by a factor of 0.5 in all axes. And lastly, we want to translate 2.0 units in x:

Matrix4f m = new Matrix4f();
m.translate(2.0f, 0.0f, 0.0f)
 .scale(0.5f)
 .rotate(90.0f, 0.0f, 1.0f, 0.0f);

Using the matrix m you can now apply this specified transformation to any Vector4f vector you want:

Vector4f v = new Vector4f(1.0f, 2.0f, 3.0f, 1.0f);
m.transform(v);

Now, the vector v will contain its transformed position (3.5, 1.0, -0.5).

Uploading the matrix

Of course you do not want your Java program to transform your model vertices. You want your graphics card to do that.

When using modern OpenGL with shaders you would now need to communicate that transformation to your shader program. There are numerous ways to do that in OpenGL, but the most common is to use a simple uniform mat4 in your shader.

Now you first have to transfer the JOML matrix into a data structure to be used by your Java/OpenGL binding. We will use LWJGL 3. With LWJGL 3 you have the option of using Java NIO Buffers for that. With JOML you would use a Java NIO FloatBuffer in the following way:

FloatBuffer fb = BufferUtils.createFloatBuffer(16);
Matrix4f m = ...;
m.get(fb);

The get method will store the matrix values in the FloatBuffer in column-major order, which is just the order that OpenGL expects the values to be in. Note that this get method does not modify the buffer position, so you would not need to rewind/flip it afterwards. You can now go ahead and use glUniformMatrix4fv to upload that FloatBuffer into your uniform mat4:

glUseProgram(theProgram);
int mat4Location = glUniformLocation(theProgram, "yourUniformName");
glUniformMatrix4fv(mat4Location, false, fb);
Clone this wiki locally