Matrices

libraries

OpenGL does not provide api to work with matrices.

For Java/Kotlin you can use JOML library. It is also provide stack for matrices (classes like Matrix4fStack).

For JavaScript, you can use the glMatrix library. For the stack, you can use a regular js array.

These libraries take in account that OpenGL uses column-major notation.

model matrix

The Model matrix defines transformations in model space: translation (i.e postion), rotation, scaling. You can read more about the math details of 3D transformations here.

camera and view matrices

The camera matrix defines position and orientation of camera or viewer in world space.

The View matrix transform from world space to view space, i.e. allows to represent world relative to the camera. This matrix is the inverse of the camera matrix.

There is method lookAt() that creates camera or view matrix. It has three parameters

  • camera position - default value in OpenGL is (0, 0, 0)
  • target - a point to which camera looks, in OpenGL defalut value is (0, 0, -1)
  • up vector - defining world's "upwards" direction, usually it has value (0, 1, 0)

viewmodel matrix

The ViewModel matrix defines transforms from model coordinates to eye coordinates. In math words, it is multiplication of view matrix and model matrix.

projection matrix

The Projection matrix is responsible for defining the visible volume. Anything outside this volume will not be visible to the camera. Usually application has only one projection matrix. You can read more about the math details of projection matrix here.

how to use matrices with shaders

Usually matrices are used as uniform variables.

in vec4 inCoords;
uniform mat4 matrix;

void main() {
    gl_Position = matrix * inCoords;
}

To bind data glUniformMatrix() functions are used.

// LWJGL+JOML
glUniformMatrix4fv(matrixLocation, false, matrix.get(matrixBuffer));

Location can be found by glGetUniformLocation() functions.

val matrixLocation = glGetUniformLocation(prog.idProgram, "matrix");

Like input attribute indices and output data locations, binding points can be set for uniforms within the shader. This is done by using the "binding" layout qualifier.

layout(binding = 1) uniform mat4 matrix;

share matrices between the shader programs

Complex app can use multiple shader programs. It is not cool to assign same projection or view matrix to each program. Fortunately, we can use a shared uniform block and to declare matrices there.

#version 330 core
layout (location = 0) in vec4 inCoords;

layout (std140) uniform Matrices
{
    mat4 projection;
    mat4 view;
};

uniform mat4 model;

void main() {
    gl_Position = projection * view * model * inCoords;
} 

Read more how to work with uniform buffer object.