/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* run.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: gbrochar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/12/23 19:38:05 by gbrochar #+# #+# */ /* Updated: 2024/04/25 16:33:52 by gbrochar ### ########.fr */ /* */ /* ************************************************************************** */ #include "scop.h" #include "mat4.h" #include "vec3.h" #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" GLuint VBO; //GLuint IBO; GLuint gScaleLocation; GLuint gTimeLocation; GLuint gProjLocation; GLuint gViewLocation; GLuint gModelLocation; GLuint gNormalLocation; GLuint texture_level_location; GLuint invert_texture_location; GLuint lighting_location; GLuint has_uvs_location; GLuint has_normals_location; //GLuint gCountLocation; GLuint index_count; GLuint gSamplerLocation; GLuint texture; const char* pVSFileName = "src/shader.vs"; const char* pFSFileName = "src/shader.fs"; static void RenderSceneCB(t_env *e) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); static float time = 0.0f; time += 0.01f; t_vec3 eye; t_vec3 up; t_vec3 target; eye.x = 0; eye.y = 0; eye.z = 2; up.x = 0; up.y = 1; up.z = 0; target.x = 0; target.y = 0; target.z = 0; t_mat4 proj = mat4_perspective(e->camera.fov * M_PI / 180.0, e->camera.aspect, e->camera.near, e->camera.far); t_mat4 view = mat4_inverse(mat4_lookat(eye, up, target)); if (e->rotating == true) { e->rotate.y += 0.01; } if (e->texture == true) { e->texture_level += 0.006; if (e->texture_level > 1) { e->texture_level = 1; } } else { e->texture_level -= 0.006; if (e->texture_level < 0) { e->texture_level = 0; } } t_mat4 model = mat4_scale( mat4_rotatexyz( mat4_translate(mat4_identity(), e->translate), e->rotate), e->scale); t_mat4 normal = mat4_transpose(mat4_inverse(mat4_multiply(view, model))); glUniform1f(gTimeLocation, time); glUniformMatrix4fv(gProjLocation, 1, GL_FALSE, (GLfloat *)proj.data); glUniformMatrix4fv(gViewLocation, 1, GL_FALSE, (GLfloat *)view.data); glUniformMatrix4fv(gModelLocation, 1, GL_FALSE, (GLfloat *)model.data); glUniformMatrix4fv(gNormalLocation, 1, GL_FALSE, (GLfloat *)normal.data); //glUniform1i(gCountLocation, index_count); glActiveTexture(GL_TEXTURE0); glUniform1i(gSamplerLocation, 0); glUniform1i(has_uvs_location, e->object.uvs.ptr); glUniform1i(has_normals_location, e->object.normals.ptr); glUniform1f(texture_level_location, e->texture_level); glUniform1i(invert_texture_location, e->invert_texture); glUniform1i(lighting_location, e->lighting); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, VBO); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0); if (e->is_good) { glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(3 * sizeof(float))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(5 * sizeof(float))); } glDrawArrays(GL_TRIANGLES, 0, index_count); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); } static void CreateVertexBuffer(t_env *e) { e->is_good = 1; if (!(e->vbo_data = (float *)malloc(e->object.vertices_indices.ptr * 8 * sizeof(float)))) { perror("malloc"); exit(0); } for (size_t i = 0; i < e->object.vertices_indices.ptr * 8; i += 8) { if (e->object.vertices_indices.data[i / 8] * 3 + 2 < e->object.vertices.ptr) { e->vbo_data[i] = e->object.vertices.data[e->object.vertices_indices.data[i / 8] * 3]; e->vbo_data[i + 1] = e->object.vertices.data[e->object.vertices_indices.data[i / 8] * 3 + 1]; e->vbo_data[i + 2] = e->object.vertices.data[e->object.vertices_indices.data[i / 8] * 3 + 2]; } if (e->object.uvs_indices.ptr == e->object.vertices_indices.ptr && e->object.uvs_indices.data[i / 8] * 2 + 1 < e->object.uvs.ptr) { e->vbo_data[i + 3] = e->object.uvs.data[e->object.uvs_indices.data[i / 8] * 2]; e->vbo_data[i + 4] = e->object.uvs.data[e->object.uvs_indices.data[i / 8] * 2 + 1]; } else { e->is_good = 0; } if (e->object.normals_indices.ptr == e->object.vertices_indices.ptr && e->object.normals_indices.data[i / 8] * 3 + 2 < e->object.normals.ptr) { e->vbo_data[i + 5] = e->object.normals.data[e->object.normals_indices.data[i / 8] * 3]; e->vbo_data[i + 6] = e->object.normals.data[e->object.normals_indices.data[i / 8] * 3 + 1]; e->vbo_data[i + 7] = e->object.normals.data[e->object.normals_indices.data[i / 8] * 3 + 2]; } else { e->is_good = 0; } } glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, e->object.vertices_indices.ptr * 8 * sizeof(float), e->vbo_data, GL_STATIC_DRAW); /* glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, e->object.vertices.ptr * sizeof(double), e->object.vertices.data, GL_STATIC_DRAW); glGenBuffers(1, &IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, e->object.vertices_indices.ptr * sizeof(int), e->object.vertices_indices.data, GL_STATIC_DRAW); */ } static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType, GLuint *shader) { *shader = glCreateShader(ShaderType); if (*shader == 0) { fprintf(stderr, "Error creating shader type %d\n", ShaderType); exit(0); } const GLchar* p[1]; p[0] = pShaderText; GLint Lengths[1]; Lengths[0] = ft_strlen(pShaderText); glShaderSource(*shader, 1, p, Lengths); glCompileShader(*shader); GLint success; glGetShaderiv(*shader, GL_COMPILE_STATUS, &success); if (!success) { GLchar InfoLog[1024]; glGetShaderInfoLog(*shader, 1024, NULL, InfoLog); fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog); exit(1); } glAttachShader(ShaderProgram, *shader); } static void CompileShaders(t_env *e) { e->shader_program = glCreateProgram(); if (e->shader_program == 0) { fprintf(stderr, "Error creating shader program\n"); exit(1); } char *vs = (char *)malloc(BUFFER_SIZE * sizeof(char)); char *fs = (char *)malloc(BUFFER_SIZE * sizeof(char)); char *buffer = (char *)malloc(BUFFER_SIZE * sizeof(char)); FILE *fp; vs[0] = '\0'; fs[0] = '\0'; fp = fopen(pVSFileName, "r"); while (fgets(buffer, 4096, fp)) { buffer[strcspn(buffer, "\n") + 1] = '\0'; strcat(vs, buffer); } fclose(fp); fp = fopen(pFSFileName, "r"); while (fgets(buffer, 4096, fp)) { buffer[strcspn(buffer, "\n") + 1] = '\0'; strcat(fs, buffer); } fclose(fp); AddShader(e->shader_program, vs, GL_VERTEX_SHADER, &(e->vertex_shader)); AddShader(e->shader_program, fs, GL_FRAGMENT_SHADER, &(e->fragment_shader)); GLint Success = 0; GLchar ErrorLog[1024] = { 0 }; glLinkProgram(e->shader_program); glGetProgramiv(e->shader_program, GL_LINK_STATUS, &Success); if (Success == 0) { glGetProgramInfoLog(e->shader_program, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Error linking shader program : '%s'\n", ErrorLog); exit(1); } glValidateProgram(e->shader_program); glGetProgramiv(e->shader_program, GL_VALIDATE_STATUS, &Success); if (!Success) { glGetProgramInfoLog(e->shader_program, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Invalid shader program '%s'\n", ErrorLog); exit(1); } glUseProgram(e->shader_program); // gScaleLocation = glGetUniformLocation(e->shader_program, "gScale"); gTimeLocation = glGetUniformLocation(e->shader_program, "time"); gProjLocation = glGetUniformLocation(e->shader_program, "proj"); gViewLocation = glGetUniformLocation(e->shader_program, "view"); gModelLocation = glGetUniformLocation(e->shader_program, "model"); gNormalLocation = glGetUniformLocation(e->shader_program, "normalMat"); gSamplerLocation = glGetUniformLocation(e->shader_program, "ourTexture"); has_uvs_location = glGetUniformLocation(e->shader_program, "has_uvs"); has_normals_location = glGetUniformLocation(e->shader_program, "has_normals"); invert_texture_location = glGetUniformLocation(e->shader_program, "invert_texture"); texture_level_location = glGetUniformLocation(e->shader_program, "texture_level"); lighting_location = glGetUniformLocation(e->shader_program, "lighting"); // assert(gScaleLocation != 0xFFFFFFFF); assert(gTimeLocation != 0xFFFFFFFF); assert(gProjLocation != 0xFFFFFFFF); assert(gViewLocation != 0xFFFFFFFF); assert(gModelLocation != 0xFFFFFFFF); free(buffer); free(vs); free(fs); } void free_shaders(t_env *e) { glDetachShader(e->shader_program, e->vertex_shader); glDetachShader(e->shader_program, e->fragment_shader); glDeleteShader(e->vertex_shader); glDeleteShader(e->fragment_shader); glUseProgram(0); glDeleteProgram(e->shader_program); } void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) { t_env *e = (t_env *)glfwGetWindowUserPointer(window); if (key == GLFW_KEY_C && (action == GLFW_PRESS)) e->invert_texture = !e->invert_texture; if (key == GLFW_KEY_N && (action == GLFW_PRESS)) e->rotating = !e->rotating; if (key == GLFW_KEY_B && (action == GLFW_PRESS)) { e->texture = !e->texture; } if (key == GLFW_KEY_V && (action == GLFW_PRESS)) { e->lighting = !e->lighting; } if (key == GLFW_KEY_Q && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.x += 0.03; if (key == GLFW_KEY_A && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.x -= 0.03; if (key == GLFW_KEY_W && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.y += 0.03; if (key == GLFW_KEY_S && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.y -= 0.03; if (key == GLFW_KEY_E && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.z += 0.03; if (key == GLFW_KEY_D && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->translate.z -= 0.03; if (key == GLFW_KEY_R && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.x += 0.03; if (key == GLFW_KEY_F && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.x -= 0.03; if (key == GLFW_KEY_T && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.y += 0.03; if (key == GLFW_KEY_G && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.y -= 0.03; if (key == GLFW_KEY_Y && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.z += 0.03; if (key == GLFW_KEY_H && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->rotate.z -= 0.03; if (key == GLFW_KEY_U && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.x *= 1.03; if (key == GLFW_KEY_J && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.x *= 0.97; if (key == GLFW_KEY_I && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.y *= 1.03; if (key == GLFW_KEY_K && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.y *= 0.97; if (key == GLFW_KEY_O && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.z *= 1.03; if (key == GLFW_KEY_L && (action == GLFW_PRESS || action == GLFW_REPEAT)) e->scale.z *= 0.97; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GLFW_TRUE); } (void)scancode; (void)mods; } int run(t_env *e) { GLFWwindow* window; /* Initialize the library */ if (!glfwInit()) return (FAILURE); /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(e->window.width, e->window.height, "SC0P", NULL, NULL); glfwSetWindowUserPointer(window, e); glfwSetKeyCallback(window, key_callback); if (!window) { glfwTerminate(); return (FAILURE); } glfwMakeContextCurrent(window); index_count = e->object.vertices_indices.ptr; GLenum res = glewInit(); if (res != GLEW_OK) { fprintf(stderr, "Error : '%s'\n", glewGetErrorString(res)); exit (1); } printf("GL version: %s\n", glGetString(GL_VERSION)); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); CreateVertexBuffer(e); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); 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); int tex_width, tex_height, nrChannels; nrChannels = -1; unsigned char *tex_data = stbi_load(e->texture_file_name, &tex_width, &tex_height, &nrChannels, 0); if (nrChannels == 4) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data); } else if (nrChannels == 3) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE, tex_data); } else { printf("error: sus text file detected, aborting NOW\n"); stbi_image_free(tex_data); glfwTerminate(); return (FAILURE); } glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(tex_data); CompileShaders(e); /* Loop until the user closes the window */ while (!glfwWindowShouldClose(window)) { /* Render here */ glClear(GL_COLOR_BUFFER_BIT); RenderSceneCB(e); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); } free_shaders(e); glfwTerminate(); return (SUCCESS); }