#include "shader.h" #include "vendor/stb_image.h" #include #include #include #include #include #include #include void on_resize(GLFWwindow *win, int width, int height) { glViewport(0, 0, width, height); } void get_max_attrib_count(int *attrib_count) { glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, attrib_count); printf("Max vertex attribs %d\n", *attrib_count); } int main() { // Initialize GLFW if (!glfwInit()) { return -1; } // Set the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow *window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); if (!window) { glfwTerminate(); return -1; } glfwSetFramebufferSizeCallback(window, on_resize); glfwMakeContextCurrent(window); // Initialize GLEW GLenum glewStatus = glewInit(); if (glewStatus != GLEW_OK) { printf("Failed to initialize GLEW: %s\n", glewGetErrorString(glewStatus)); return -1; } int attrib_count; get_max_attrib_count(&attrib_count); unsigned int texture1, texture2; glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); // Changed from texture to texture1 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); float borderColor[] = {1.0f, 1.0f, 0.0f, 1.0f}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int width, height, nrChannels; unsigned char *data = stbi_load("res/images/container.jpg", &width, &height, &nrChannels, 0); if (data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { printf("Failed to load texture\n"); } stbi_image_free(data); glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_set_flip_vertically_on_load(true); data = stbi_load("res/images/awesomeface.png", &width, &height, &nrChannels, 0); // Removed asterisk if (data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // Changed GL_RGB to GL_RGBA glGenerateMipmap(GL_TEXTURE_2D); } else { printf("Failed to load texture\n"); } stbi_image_free(data); float vertices[] = { // positions // texture coords 0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left -0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left }; unsigned int indices[] = { 0, 1, 3, // first triangle 1, 2, 3 // second triangle }; unsigned int VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); Shader *shader = shader_create("src/shaders/triangle.vert.glsl", "src/shaders/triangle.frag.glsl"); if (!shader) { glfwTerminate(); return -1; } // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); // color attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(6 * sizeof(float))); glEnableVertexAttribArray(2); shader_use(shader); glUniform1i(glGetUniformLocation(shader->program, "texture1"), 0); glUniform1i(glGetUniformLocation(shader->program, "texture2"), 1); while (!glfwWindowShouldClose(window)) { glClearColor(0.1f, 0.1f, 0.25f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); mat4 trans; glm_mat4_identity(trans); glm_rotate(trans, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f}); unsigned int transform_location = glGetUniformLocation(shader->program, "transform"); glUniformMatrix4fv(transform_location, 1, GL_FALSE, (float *)trans); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); shader_delete(shader); glfwTerminate(); return 0; }