diff --git a/src/graphics/shaders_study.c b/src/graphics/shaders_study.c new file mode 100644 index 0000000..e23e816 --- /dev/null +++ b/src/graphics/shaders_study.c @@ -0,0 +1,159 @@ +/* + * Gem-graph OpenGL experiments + * + * Desc: GL functions + * + * Copyright (C) 2023 Arthur Menges + * Copyright (C) 2023 Adrien Bourmault + * Copyright (C) 2023 Jean Sirmai + * + * This file is part of Gem-graph. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "../../include/base.h" +#include "../../include/ui.h" +#include "../../include/graphics.h" +#include "../../include/shaders_study.h" +#include "../../include/arrows.h" +#include "../../include/grid.h" + +#define VERTEX_SHADER_FILE "src/shaders/shader.vert" +#define FRAG_SHADER_FILE "src/shaders/shader.frag" + + +// Que fait l'instruction suivante (ligne 397 de graphics.c) +// dans "bool graphics_init(const char *gl_area)" ? +// +// if (!graphics_init_shaders(gl_area)) return false; +// +// Et comment et pourquoi cette structure "gl_area_array" ? +// (Dynamic array of ptrs to dynamically allocated gl_area_entry) +// +// struct gl_area_entry **gl_area_array = NULL; + + + +/* + * Initializes the shaders of a gl_area and link them to a program + * + * @param gl_area, ptr to the gl_area widget + * + * @return true if initialized + */ +bool graphics_init_shaders(const void *gl_area) +{ + char *vertex_shader; + char *fragment_shader; + struct gl_area_entry *entry; + int status; + GLuint vertex, fragment; + GLuint program = 0; + GLuint m = 0; + GLuint v = 0; + GLuint p = 0; + + entry = graphics_find_glarea_from_ptr(gl_area); + + if (entry == NULL) { + errno = EFAULT; + perror("gl_area_array entry not found"); + return false; + } + + // Load vertex shader file + vertex_shader = read_file(VERTEX_SHADER_FILE); + if (vertex_shader == NULL) + return false; + vertex = create_shader(GL_VERTEX_SHADER, vertex_shader); + +// ! WARNING ! l'instruction suivante (ou un autre 'free') a pu provoquer un 'double free' (Abandon) + if(vertex == 0) { + entry->program = 0; + g_free(vertex_shader); + return false; + } + + // Load fragment shader file + fragment_shader = read_file(FRAG_SHADER_FILE); + if (fragment_shader == NULL) + return false; + fragment = create_shader(GL_FRAGMENT_SHADER, fragment_shader); + + if(fragment == 0) { + glDeleteShader(vertex); + entry->program = 0; + g_free(vertex_shader); + g_free(fragment_shader); + return false; + } + + // Link shaders to program + program = glCreateProgram(); + glAttachShader(program, vertex); + glAttachShader(program, fragment); + + glLinkProgram(program); + + glGetProgramiv(program, GL_LINK_STATUS, &status); + + if(status == GL_FALSE) { + int log_len; + char *buffer; + + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); + + buffer = g_malloc(log_len + 1); + assert(buffer); + glGetProgramInfoLog(program, log_len, NULL, buffer); + + g_warning("Linking failure:\n%s", buffer); + + g_free(buffer); + + glDeleteProgram(program); + program = 0; + + glDeleteShader(vertex); + glDeleteShader(fragment); + + g_free(vertex_shader); + g_free(fragment_shader); + + return false; + } + + /* Get the location of the "mvp" uniform */ + m = glGetUniformLocation(program, "model_matrix"); + v = glGetUniformLocation(program, "view_matrix"); + p = glGetUniformLocation(program, "projection_matrix"); + + glDetachShader(program, vertex); + glDetachShader(program, fragment); + + glDeleteShader(vertex); + glDeleteShader(fragment); + + entry->program = program; + entry->m = m; + entry->v = v; + entry->p = p; + + g_free(vertex_shader); + g_free(fragment_shader); + + return true; +} +