Issue
I've recently started a project with LWJGL 3 (Lightweight Java Game Library 3) and Java, and I've been trying to render a simple cube. However, my code currently displays an empty black screen.
This is my render code:
public void renderObject(Camera camera, ShaderProgram shader) {
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
Matrix4f mvpMatrix = Matrix4f.multiply(projection, Matrix4f.multiply(entity.modelMatrix(), view));
shader.uniformMatrix4f("mvpMatrix", mvpMatrix);
indexBuf.bind();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
entity.getTexturedMesh().bindTexture();
GL11.glDrawElements(GL11.GL_TRIANGLES, entity.getTexturedMesh().mesh.getIndexVec().size(), GL11.GL_UNSIGNED_INT, 0);
indexBuf.unbind();
vao.unbind();
shader.stop();
}
This is my vertex shader:
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
out vec3 color;
out vec2 pass_texCoords;
uniform mat4 mvpMatrix;
void main(void) {
gl_Position = mvpMatrix * vec4(position, 1.0);
color = vec3(0.0, 1.0, 0.0);
pass_texCoords = texCoords;
}
This is my fragment shader:
#version 450 core
in vec3 color;
in vec2 pass_texCoords;
out vec4 out_color;
uniform sampler2D textureSampler;
void main(void) {
out_color = texture(textureSampler,pass_texCoords);
}
(FYI, Matrix4f is a custom math class that I made. )
Remarks: I discovered that if I change gl_Position = mvpMatrix * vec4(position, 1.0)
to glPosition = vec4(position, 1.0)
, then it renders (although I can see only one face of the cube). One can therefore infer that the problem is with mvpMatrix
.
However, I made two other discoveries that seemed to contradict my hypothesis.
First, I printed out the mvpMatrix
in renderObject
and found that it was indeed correct.
Therefore, I deduced that the problem must be with the function uniformMatrix4f()
, which was supposed to pass the uniform from the code to the shader.
To test my hypothesis, I decided to make a uniform matrix called testMatrix
, which was just
[0, 0, 0, 0]
[0, 1, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
and added this line to the code:
shader.uniformMatrix4f("testMatrix", testMatrix);
I had also discovered that you can debug shaders by passing the value to the color.
Therefore, I changed gl_Position = mvpMatrix * vec4(position, 1.0)
to glPosition = vec4(position, 1.0)
and out_color = texture(textureSampler,pass_texCoords)
to out_color = vec4(color, 1.0)
.
Then I changed color = vec3(0.0, 1.0, 0.0)
to
color = vec3(testMatrix[0][0], testMatrix[1][1], testMatrix[2][2]);
If my hypothesis were correct, as I expected, then I would probably get a blank screen. However, if my hypothesis were false, the color would be vec3(0, 1, 0)
, or green, and I would see a green square.
When I rendered it, I saw a green square, not a blank screen, which was extremely puzzling, and since I can't find any other source of the problem, I'm stuck.
Solution
It's been very, VERY long since I solved this problem, but I realized I was storing the transpose of the matrix instead of the matrix itself when I was putting the uniform to the shader. The reason why my color = vec3(testMatrix[0][0], testMatrix[1][1], testMatrix[2][2])
didn't work was because the matrix values I checked were all on the diagonal, which means they were unaffected.
I fixed this by simply changing the 'transposed' attribute from false to true.
GL20.glUniformMatrix4fv(loc, false, matrixBuffer);
->
GL20.glUniformMatrix4fv(loc, true, matrixBuffer);
More explanation:
I was using a one-dimensional array buffer to store the matrix (as this made it easier to store it into the uniform buffer).
Here is a 4x4 matrix for reference:
m00 m01 m02 m03
m10 m11 m12 m13
m20 m21 m22 m23
m30 m31 m32 m33
To convert the two-dimensional coordinates to the one-dimensional coordinates, I used this function:
m[x][y] -> [x + y * sz]
Which means that my array was mapped like this:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
I thought this was the right order. But it turns out this is exactly the transpose of the order I needed to put my matrices in!
I don't want this answer to get too lengthy, but you can find more info here.
Answered By - new QOpenGLWidget
Answer Checked By - Katrina (JavaFixing Volunteer)