I'm trying to draw a triangle using only shaders. That means no glRotate(), glTranslate(), or anything else relating to the immediate mode matrices.
I noticed thatLWJGL's Matrix4f class has all the methods that I need (rotate(), translate(), etc.) and a convenient way to store it into a FloatBuffer (store()).
I could render a triangle just fine, but when I tried to start using a rotation matrix things stopped working (the dreaded blank screen of doom).
In my vertex shader, I have
uniform mat4 RotationMatrix
Every rendering loop I set it to a rotated Matrix4f (stored in a FloatBuffer) using the following code:
// create a new matrix
Matrix4f rotationMatrix = new Matrix4f();
// set it to the identity matrix
rotationMatrix.setIdentity();
// rotate it by angle along the Z axis
rotationMatrix = rotationMatrix.rotate(angle, new Vector3f(0.0f, 0.0f, 1.0f));
// buffer for transferring matrix to shader
FloatBuffer rotBuffer = BufferUtils.createFloatBuffer(16);
// store the matrix in the buffer
rotationMatrix.store(rotBuffer);
// get the location of RotationMatrix
int location = GL20.glGetUniformLocation(program.getHandle(), "RotationMatrix");
if(location >= 0){
// set the rotation matrix
GL20.glUniformMatrix4(location, false, rotBuffer);
}
To calculate the position in the vertex shader, I use
gl_Position = RotationMatrix * vec4(VertexPosition,1.0);
I know that the shaders are all compiled and linked properly, and the RotationMatrix shows up in the program's active uniforms list.
So what am I doing wrong here? I tried using the transpose of the matrix and it didn't help. Is using LWJGL's Matrix4f class a bad idea for this sort of stuff?
Here's my vertex shader (I know my fragment shader works):
#version 400
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexColor;
out vec3 Color;
uniform mat4 RotationMatrix;
void main()
{
Color = VertexColor;
gl_Position = RotationMatrix * vec4(VertexPosition,1.0);
}
And my initialization and rendering loop (window is created elsewhere, GLSLProgram and GLSLShader are classes I wrote to compile and link shaders with):
package spaceguts.graphics.glsl;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import spaceguts.util.DisplayHelper;
import spaceguts.util.resources.Paths;
public class GLSLRender {
static int vaoHandle = 0;
private static GLSLProgram program;
private static float angle = 30.0f;
public static void render(){
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
/* BEGIN CODE THAT DOESN'T WORK */
// create a new matrix
Matrix4f rotationMatrix = new Matrix4f();
// set it to the identity matrix
rotationMatrix.setIdentity();
// rotate it by angle along the Z axis
rotationMatrix = rotationMatrix.rotate(angle, new Vector3f(0.0f, 0.0f, 1.0f));
// increase angle
//angle += 0.05f;
// buffer for transferring matrix to shader
FloatBuffer rotBuffer = BufferUtils.createFloatBuffer(16);
// store the matrix in the buffer
rotationMatrix.store(rotBuffer);
// get the location of RotationMatrix
int location = GL20.glGetUniformLocation(program.getHandle(), "RotationMatrix");
if(location >= 0){
// set the rotation matrix
GL20.glUniformMatrix4(location, false, rotBuffer);
} else{
System.out.println("RotationMatrix uniform not found");
}
/* END CODE THAT DOESN'T WORK */
// draw triangle
GL30.glBindVertexArray(vaoHandle);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
}
public static void initGL(){
// set the viewport
GL11.glViewport(0, 0, DisplayHelper.windowWidth, DisplayHelper.windowHeight);
// set the clear color
GL11.glClearColor(0.2f,0.2f,0.2f,1.0f);
// create vertex shader
GLSLShader vertShader = new GLSLShader(ShaderTypes.VERTEX);
String vertFile = Paths.SHADER_PATH.path() + "basic_uniform.vert";
if(!vertShader.compileShaderFromFile(vertFile))
System.out.println(vertShader.log());
// create fragment shader
GLSLShader fragShader = new GLSLShader(ShaderTypes.FRAGMENT);
String fragFile = Paths.SHADER_PATH.path() + "basic_uniform.frag";
if(!fragShader.compileShaderFromFile(fragFile)){
System.out.println(fragShader.log());
}
// create and use program
program = new GLSLProgram();
program.addShader(fragShader);
program.addShader(vertShader);
program.link();
program.use();
program.printActiveUniforms();
program.printActiveAttribs();
/* BEGIN VERTEX ARRAY */
// create vertex buffer object handles
IntBuffer vboHandles = BufferUtils.createIntBuffer(2);
GL15.glGenBuffers(vboHandles);
// create poisition data
int positionBufferHandle = vboHandles.get(0);
FloatBuffer positionBuffer = BufferUtils.createFloatBuffer(9);
float[] positionData = {
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f };
positionBuffer.put(positionData);
positionBuffer.rewind();
// point the vertex buffer at the position data
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionBufferHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, positionBuffer, GL15.GL_STATIC_DRAW);
// create color data
int colorBufferHandle = vboHandles.get(1);
FloatBuffer colorBuffer = BufferUtils.createFloatBuffer(9);
float[] colorData = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
colorBuffer.put(colorData);
colorBuffer.rewind();
// point the vertex buffer at the color data
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorBufferHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorBuffer, GL15.GL_STATIC_DRAW);
// generate vertex array object
vaoHandle = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoHandle);
// enable 0 (VertexPosition) and 1 (VertexColor) - see bindAttribLocation call
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionBufferHandle);
// 0 (VertexPosition) has three elements per vertex, is of type float, is not normalized, the data is tightly packed (0 stride), and there's no offset
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0L);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, colorBufferHandle);
// 1 (VertexColor) has three elements per vertex, is of type float, is not normalized, it tightly packed, and there's no offset
GL20.glVertexAttribPointer(1, 3, GL11.GL_FLOAT, false, 0, 0L);
}
}