diff --git a/src/main.cpp b/src/main.cpp index 8c8440f..5e6de88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,116 @@ #include +#include #include #include // Window dimensions const GLint WIDTH = 800, HEIGHT = 600; +// Vertex Shader +static const char *vertex_shader = " \n\ +#version 330 \n\ + \n\ +layout (location = 0) in vec3 pos; \n\ + \n\ +void main() { \n\ + gl_Position = vec4(pos.x, pos.y, pos.z, 1.0); \n\ +}"; + +// Fragment shader +static const char *fragment_shader = " \n\ +#version 330 \n\ + \n\ +out vec4 color; \n\ + \n\ +void main() { \n\ + color = vec4(1.0, 0.0, 0.0, 1.0); \n\ +}"; + +bool add_shader(GLuint *program, const char *shader_code, GLenum shader_type) { + GLuint shader = glCreateShader(shader_type); + const GLchar *code[1]; + code[0] = shader_code; + + GLint code_length[1]; + code_length[0] = strlen(shader_code); + + glShaderSource(shader, 1, code, code_length); + glCompileShader(shader); + + GLint result = 0; + GLchar errors[1024] = { 0 }; + + glGetShaderiv(shader, GL_COMPILE_STATUS, &result); + if (!result) { + glGetShaderInfoLog(shader, sizeof(errors), NULL, errors); + printf("Error compiling the %d shader: '%s'\n", shader_type, errors); + return false; + } + + glAttachShader(*program, shader); + return true; +} + +bool compile_shaders(GLuint *shader_program) { + *shader_program = glCreateProgram(); + + if (!shader_program) { + printf("Error creating shader program!\n"); + return false; + } + + add_shader(shader_program, vertex_shader, GL_VERTEX_SHADER); + add_shader(shader_program, fragment_shader, GL_FRAGMENT_SHADER); + + GLint result = 0; + GLchar errors[1024] = { 0 }; + + glLinkProgram(*shader_program); + glGetProgramiv(*shader_program, GL_LINK_STATUS, &result); + + if (!result) { + glGetProgramInfoLog(*shader_program, sizeof(errors), NULL, errors); + printf("Error linking program: '%s'\n", errors); + return false; + } + + glValidateProgram(*shader_program); + glGetProgramiv(*shader_program, GL_VALIDATE_STATUS, &result); + + if (!result) { + glGetProgramInfoLog(*shader_program, sizeof(errors), NULL, errors); + printf("Error validating program: '%s'\n", errors); + return false; + } + + return true; +} + +void create_triangle(GLuint *VAO, GLuint *VBO) { + GLfloat vertices[] = { + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 0.0f, 1.0f, 0.0f + }; + + glGenVertexArrays(1, VAO); + glBindVertexArray(*VAO); + + glGenBuffers(1, VBO); + glBindBuffer(GL_ARRAY_BUFFER, *VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(0); + + // Unbinding + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} int main() { + GLuint VAO, VBO, shader_program; + // Initialize GLFW glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND); @@ -19,7 +123,6 @@ int main() { // Setup GLFW window properties // OpenGL version - // @Reminder Look into making it work on Wayland glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); // Core profile means it will not be backwards compatible @@ -63,23 +166,35 @@ int main() { // Setup viewport size glViewport(0, 0, buffer_width, buffer_height); + // Create our triangle + create_triangle(&VAO, &VBO); + compile_shaders(&shader_program); + // Loop until window is closed while (!glfwWindowShouldClose(window)) { // Get and handle user input events glfwPollEvents(); // Clear window - glClearColor(1.0f, 0.9f, 0.4f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(shader_program); + glBindVertexArray(VAO); + glDrawArrays(GL_TRIANGLES, 0, 3); - // We usually have two buffers, the first is hidden and that's the one - // we draw to. The second is the one we display, so when we're done drawing - // we call this glfwSwapBuffers() to swap the buffers to show the one we've - // been drawing to so that it now shows. We then can start drawing on the - // other buffer. + glBindVertexArray(0); + glUseProgram(0); + + + // We usually have two buffers, the first is hidden and that's + // the one we draw to. The second is the one we display, so + // when we're done drawing we call this glfwSwapBuffers() to + // swap the buffers to show the one we've been drawing to so + // that it now shows. We then can start drawing on the other + // buffer. glfwSwapBuffers(window); } return 0; -} \ No newline at end of file +}