JOML-CI / JOML

A Java math library for OpenGL rendering calculations
MIT License
729 stars 104 forks source link

Separate View Matrix and Projection Matrix #302

Closed extorc closed 3 years ago

extorc commented 3 years ago

In the README.md example for camera creation the provided code is

Matrix4f m = new Matrix4f()
     .perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f)
     .lookAt(0.0f, 0.0f, 10.0f,
             0.0f, 0.0f, 0.0f,
             0.0f, 1.0f, 0.0f);
// the camera transformation is now in m

Here we are keeping perspective projection and view matrix in the same Matrix4f which means we cannot exclusively access View matrix.
Is there a way i can have a

Matrix4f m = new Matrix4f()
    .perspective((float) Math.toRadians(45.0f), 1.0f, 0.01f, 100.0f);

and

Matrix4f m = new Matrix4f() .lookAt(0.0f, 0.0f, 10.0f,
             0.0f, 0.0f, 0.0f,
             0.0f, 1.0f, 0.0f);
// the camera transformation is now in m


And later they may be combined in the GLSL shader. This mechanism doesnot work

httpdigest commented 3 years ago

Is there a way i can have a [...perfectly fine and working code...] and [...other perfectly fine and working code...] And later they may be combined in the GLSL shader.

Yes. And it would work exactly like you outlined it. Simply allocate two Matrix4f instances, call perspective (or setPerspective) on the first and call lookAt (or setLookAt) on the second.

extorc commented 3 years ago

@httpdigest With View and Projection in same matrix. image With separated matrices and passed to shader and multiplied. image

#version 400 core

in vec3 position;
in vec2 tCords;
in vec3 normal;

out vec2 o_tCords;
out vec3 surfaceNormal;
out vec3 toLightVector;

uniform mat4 t;
uniform mat4 p;
uniform mat4 v;

uniform vec3 Lightposition;

void main(){
    gl_Position =  v * p * t * vec4(position, 1.0);
    o_tCords = tCords;

    surfaceNormal = (t * vec4(normal,0.0)).xyz;
    toLightVector = Lightposition - (t * vec4(position, 1.0)).xyz;
}

Data passed into shader

shader.SetUniformMat4("p", camera.pMatrix);
        shader.SetUniformMat4("v", camera.vMatrix);
        shader.SetUniformMat4("t", mMatrix);

Matrices

    public Matrix4f pMatrix = new Matrix4f().perspective((float) Math.toRadians(10.0f), 16.0f/9.0f,0.1f, 1000f);
    public Matrix4f vMatrix = new Matrix4f().lookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
httpdigest commented 3 years ago

The problem is your (wrong) multiplication order in the shader:

gl_Position =  v * p * t * vec4(position, 1.0);

It should be:

gl_Position =  p * v * t * vec4(position, 1.0);

With JOML you also wouldn't do: new Matrix4f().lookAt(...).perspective(...);. It's basically the same in JOML as in GLSL: Vectors are column vectors and matrix/vector multiplications are: matrix * vector, hence it is: projectionMatrix * viewMatrix * modelMatrix * modelPosition.

extorc commented 3 years ago

Yup, that works. Thanks.