Skip to content

JOML and modern OpenGL

Kai Burjack edited this page Jan 7, 2016 · 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).

Camera transformation

Typically, you need rotate, scale and translate to transform your models in the scene. For a camera transformation, this would be quite unhandy. For this you can use Matrix4f.lookAt() to position your camera in the scene and make it look at a given point.

Since you also most likely want to have a perspective projection, where objects closer to the camera appear bigger than objects farther away, you can use Matrix4f.perspective(), which applies a symmetric-frustum perspective projection:

Matrix4f m = new Matrix4f();
m.perspective((float) Math.toRadians(45), (float)width/height, 0.01f, 100.0f)
 .lookAt(0.0f, 1.0f, 5.0f,
         0.0f, 0.0f, 0.0f,
         0.0f, 1.0f, 0.0f);

The above will create a perspective camera transformation and locate the camera at (0, 1, 5) and make it look at the origin.

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 = glGetUniformLocation(theProgram, "yourUniformName");
glUniformMatrix4fv(mat4Location, false, fb);
Clone this wiki locally