I have been trying to learn OpenGL recently. I am a quite confused on the correct usage of glBindAttribLocation
because I thought that it sets attributes in the shader(such as in vec3 position;
) to data in the VAO (for example attribute 0 in the VAO). However when I comment out the line(line 136) the triangle still renders fine with it's colours so the shader must know about the position and colour data some other way, but I'm confused as to how. What line tells the shader about the data or does the shader just automatically read the attributes in from a VAO?
I was told in a previous question that the line needs to be before the shader linking so I moved it around but the line still doesn't seem to make a difference in my program.
here is the link to my code (its 215 lines): https://github.com/OneEgg42/opengl/blob/main/Main.java
my code:
public static void main(String[] args) {
//see text file for all the comments
String vertexSource = "#version 400 core\n"
+ "in vec3 position;\n"
+ "in vec3 colour;\n"
+ "out vec3 vertexColour;\n"
+ "uniform mat4 model;\n"
+ "uniform mat4 view;\n"
+ "uniform mat4 projection;\n"
+ "void main() {\n"
+ "vertexColour = colour;\n"
+ "mat4 mvp = projection * view * model;\n"
+ "gl_Position = vec4(position, 1.0);\n"
+ "}\n";
String fragmentSource = "#version 400 core\n"
+ "in vec3 vertexColour;\n"
+ "out vec4 colours;\n"
+ "void main()\n"
+ "{\n"
+ " colours = vec4(vertexColour, 1);\n"
+ "}";
glfwSetErrorCallback(errorCallBack);
if (!glfwInit()) {
throw new IllegalStateException("Unable to initialize GLFW");
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
long window = glfwCreateWindow(640, 480, "my window!", 0, 0);
glfwSetKeyCallback(window, keyCallback);
if (window == 0) {
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
glfwMakeContextCurrent(window);
GL.createCapabilities();
//the openGL positions
float[] vertexPoints = {
0f,0.5f,0f,
-0.5f,-0.5f,0f,
0.5f,-0.5f,0f
};
float[] colours = {
0.1f,0.5f,0.5f,
0.3f,0.7f,0.9f,
0.4f,0.9f,0.1f
};
//so that we can delete the vbos and vaos later
ArrayList<Integer> vaos = new ArrayList<Integer>();
ArrayList<Integer> vbos = new ArrayList<Integer>();
//creating an empty VAO and it returns the id of that vao
int vaoID = glGenVertexArrays();
vaos.add(vaoID);
glBindVertexArray(vaoID);
FloatBuffer vertices = BufferUtils.createFloatBuffer(vertexPoints.length);
vertices.put(vertexPoints);
vertices.flip();
int vboID = GL33.glGenBuffers();
vbos.add(vboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
//and one for the colour data
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, colours, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
int vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
int fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
int shaderProgramID = glCreateProgram();
int floatSize = 4;//4 bytes
int positionAttribute = glGetAttribLocation(shaderProgramID, "position");
glEnableVertexAttribArray(positionAttribute);
glBindAttribLocation(shaderProgramID, positionAttribute, "position");
//setting colour attribute in the shader:
int colourAttribute = glGetAttribLocation(shaderProgramID, "colour");
glEnableVertexAttribArray(colourAttribute);
//glVertexAttribPointer(colourAttribute, 3, GL_FLOAT, false, 6 * floatSize, 3 * floatSize);
glBindAttribLocation(shaderProgramID, colourAttribute, "colour");
//vertex
glShaderSource(vertexShaderID, vertexSource);
glCompileShader(vertexShaderID);
if (!checkForSuccess(vertexShaderID)) {
glfwTerminate();
throw new IllegalStateException("vertex shader failed: " + glGetShaderInfoLog(vertexShaderID));
}
//fragment
glShaderSource(fragmentShaderID, fragmentSource);
glCompileShader(fragmentShaderID);
if (!checkForSuccess(vertexShaderID)) {
glGetShaderInfoLog(vertexShaderID);
glfwTerminate();
throw new IllegalStateException("fragment shader failed");
}
//shader program
glAttachShader(shaderProgramID, vertexShaderID);
glAttachShader(shaderProgramID, fragmentShaderID);
glLinkProgram(shaderProgramID);
//error test
int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
if (status != GL_TRUE) {
glfwTerminate();
throw new RuntimeException(glGetProgramInfoLog(shaderProgramID));
}
glUseProgram(shaderProgramID);
////////////////////////////////////////////////////////////////////////////// glClearColor(0.5f,0.5f,0.5f,1f);
//this will create a wire frame view
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glfwShowWindow(window); //optional
while (!glfwWindowShouldClose(window)) {
double time = glfwGetTime();
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vaoID);
glDrawArrays(GL_TRIANGLES, 0, vertexPoints.length);
glfwSwapBuffers(window);
}
//clear vaos and vbos
for (int vao : vaos) {
glDeleteVertexArrays(vao);
}
for (int vbo : vbos) {
glDeleteBuffers(vbo);
}
//delete shaders
glDetachShader(shaderProgramID, vertexShaderID);
glDetachShader(shaderProgramID, fragmentShaderID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
glDeleteProgram(shaderProgramID);
Callbacks.glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
}
public static boolean checkForSuccess(int shaderID) {
int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
return status == GL_TRUE;
}
Thanks in advance for any help!