javamatrixlwjglprojection-matrixjoml

LWJGL Projection Matrix not working (Quad remains the same even after multiplying with Projection Matrix)


I programmed a LWJGL 3 code to render a quad on the screen. I even added the projection Matrix to it, still I don't see any changes in the appearance of the quad. If I change the FOV of the frustum the quad gets smaller (that's what I expected) but the quad remains a rectangle even though it should have been a square!

Here is the Renderer Class:

    ShaderReader reader = new ShaderReader();
    Shader shader = null;
    Mesh mesh;
    
    private static final float FOV = 45f;
    private static final float Z_NEAR = 0.01f;
    private static final float Z_FAR = 1000f;
    private static Matrix4f projectionMatrix;
    
    float[] vertices = {
            -0.5f, 0.5f, -5.0f,
            -0.5f, -0.5f,-5.0f,
            0.5f, -0.5f, -5.0f,
            0.5f, 0.5f, -5.0f
    };
    
    int[] indices = {
            0,1,3,
            3,1,2
    };
    
    public void init(Window window) {
        GL11.glClearColor(.2f, .8f, 1f, 1f);
        shader = new Shader(reader);
        
        shader.createVertexShader(reader.readFile("shader.vs"));
        shader.createFragmentShader(reader.readFile("shader.fs"));
        
        shader.link();
        
        mesh = new Mesh(vertices, indices);
        
        float aspectRatio = 640 / 480;
        
        projectionMatrix = new Matrix4f();
        projectionMatrix.perspective((float) (Math.toRadians(FOV)), 1, Z_NEAR, Z_FAR);
    }
    
    public void clear() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    }
    
    public void render() {
        clear();
        
        shader.bind();
        
        shader.setUniform("projectionMatrix", projectionMatrix);
        
        GL30.glBindVertexArray(mesh.getVaoID());
        GL20.glEnableVertexAttribArray(0);
        
        GL11.glDrawElements(GL11.GL_TRIANGLES, mesh.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);;
        
        GL20.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }

Here is the Shader Class:

private int programID;
    private int vertexShaderID;
    private int fragmentShaderID;
    
    public Shader(ShaderReader reader) {
        programID = GL20.glCreateProgram();
        if (programID ==0)  {
            System.err.println("Error : Couldn't create program");
        }
    }
    
    public void createVertexShader(String shaderCode) {
        vertexShaderID = createShader(shaderCode, GL20.GL_VERTEX_SHADER);
    }
    
    public void createFragmentShader(String shaderCode) {
        fragmentShaderID = createShader(shaderCode, GL20.GL_FRAGMENT_SHADER);
    }
    
    private int createShader(String shaderCode, int type) {
        int shaderID = GL20.glCreateShader(type);
        if (shaderID == 0) {
            System.err.println("Error : Couldn't create shader");
        }
        
        GL20.glShaderSource(shaderID, shaderCode);
        GL20.glCompileShader(shaderID);
        
        if ((GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS)) != 1) {
            System.err.println("Error: Couldn't Compile Shader, " + GL20.glGetShaderInfoLog(shaderID));
        } 
        
        GL20.glAttachShader(programID, shaderID);
        
        return shaderID;
    }
    
    public void link() {
        GL20.glLinkProgram(programID);
        
        if ((GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS)) != GL11.GL_TRUE) {
            System.err.println("Error: Couldn't Link Program, " + GL20.glGetProgramInfoLog(programID, 1024));
        }
        
        if (vertexShaderID != 0) {
            GL20.glDetachShader(vertexShaderID, programID);
        }
        
        if (fragmentShaderID != 0) {
            GL20.glDetachShader(fragmentShaderID, programID);
        }
        GL20.glValidateProgram(programID);
        
        if ((GL20.glGetProgrami(programID, GL20.GL_VALIDATE_STATUS)) != GL11.GL_TRUE) {
            System.err.println("Error: Couldn't Validate Program, " + GL20.glGetProgramInfoLog(programID));
        }
        
        
    }
    
    public void setUniform(String name, Matrix4f mat) {
        int location = GL20.glGetUniformLocation(programID, name);
        FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
        mat.get(buffer);
        GL20.glUniformMatrix4fv(location, false, buffer);
    } 
    
    public void bind() {
        GL20.glUseProgram(programID);
    }
    
    public void unBind() {
        GL20.glUseProgram(0);
    }

the source folder of my project :https://www.dropbox.com/scl/fo/hwlnz913jm6c9xli2dsb6/h?dl=0&rlkey=b2zj0w6kttwu3b1di9rejwnq3

[The Quad that gets rendered] (https://i.sstatic.net/H932c.jpg)

I first used JOML to program the projection matrix and also tried to calculate and put the values in the matrix individually still the quad was showing up as a rectangle and not a square even though the size changed when I change FOV. Please Help!


Solution

  • Your code for computing the projection matrix has multiple issues:

    float aspectRatio = 640 / 480;
    projectionMatrix = new Matrix4f();
    projectionMatrix.perspective((float) (Math.toRadians(FOV)), 1, Z_NEAR, Z_FAR);
    

    First of all, the division 640 / 480 is an integer division, so will always be exactly 1, regardless of later being assigned to a float variable.

    And second, you do not actually use this variable in the call to perspective. You simply use the literal constant 1 here as the argument.

    So, change the computation of the aspect ratio e.g. to (float) 640 / 480 or 640f / 480 and actually use the aspectRatio variable as the second argument to the perspective call:

    float aspectRatio = (float) 640 / 480;
    projectionMatrix = new Matrix4f();
    projectionMatrix.perspective((float) (Math.toRadians(FOV)), aspectRatio, Z_NEAR, Z_FAR);