I followed LearnOpenGL guide and in the final part, when it was supposed to be drawing the triangle, it just didn’t.
There’s no compile or runtime errors, I just get the empty window. Since I’m a beginner I don’t know how to track the problem, like checking whatever is inside my buffers.
My main file:
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.h"
#define ASSERT(x, str) if (!(x)) {printf(str); exit(1);}
#define WIDTH 800
#define HEIGHT 800
typedef unsigned int uint;
typedef uint8_t u8;
typedef uint16_t u16;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef float f32;
typedef double f64;
// ---
typedef struct {
GLFWwindow* window;
} Canvas;
Canvas canvas;
f32 vertices[] = {
0.25, 0.25, 0,
0.75, 0.25, 0,
0.50, 0.75, 0
};
// ---
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
}
int main() {
// Start OpenGL
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create a window
canvas.window = glfwCreateWindow(WIDTH, HEIGHT, "", NULL, NULL);
ASSERT(canvas.window, "Failed to create a window");
glfwMakeContextCurrent(canvas.window);
ASSERT(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress), "Failed loading glad");
glViewport(0, 0, WIDTH, HEIGHT);
// Bind VBO and insert vertices into it
uint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Compile vertex shader
uint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
i32 success;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
ASSERT(success, "Error compiling vertex shader");
// Compile vertex shader
uint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
ASSERT(success, "Error compiling fragment shader");
// Create shader program
uint shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
ASSERT(success, "Error linking shaders");
glUseProgram(shader_program);
// Link vertex
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*) 0);
glEnableVertexAttribArray(0);
// Create VAO
uint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(canvas.window);
// Just a test area where I placed every necessary stuff
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*) 0);
glEnableVertexAttribArray(0);
glUseProgram(shader_program);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// Main loop
while(!glfwWindowShouldClose(canvas.window)) {
processInput(canvas.window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
My shaders:
const char* vertex_shader_source = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;"
"void main() {"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1);"
"}\0";
const char* fragment_shader_source = "#version 330 core\n"
"out vec4 color;"
"void main() {"
" color = vec4(1, 1, 1, 1);"
"}\0";
I just hope this is something really dumb instead of a problem with that glad (glad is a black-box for me)
>Solution :
You have to generate and bind the VAO (glGenVertexArrays, glBindVertexArray) before specifying the vertices with glVertexAttribPointer. When defining an array of generic vertex attribute data with glVertexAttribPointer, the corresponding buffer object and vertex array object must be bound. glVertexAttribPointer stores the ID of the buffer bound to the GL_ARRAY_BUFFER target in the state vector of the vertex array object that is currently bound.
uint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
uint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*) 0);
glEnableVertexAttribArray(0);
When drawing the mesh, it is sufficient to bind the VAO with the vertex specification of the mesh:
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);