From 00ff773ea10dba1fd4c1a2bb09c1ec811a798af3 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 15 Sep 2019 14:21:43 +0200 Subject: WIP: utils.c for factoring opengl tedious tasks, switch to OpenGL 3.3 For now, it display nothing, shaders changed without updating client code. --- res/scene01_fs_colorfultest.glsl | 5 ++ res/scene01_vs_basic.glsl | 12 +++++ src/Makefile.am | 2 +- src/demoscene-eo.c | 6 +-- src/scene01.c | 80 ++++++--------------------- src/utils.c | 114 +++++++++++++++++++++++++++++++++++++++ src/utils.h | 13 +++++ 7 files changed, 165 insertions(+), 67 deletions(-) create mode 100644 res/scene01_fs_colorfultest.glsl create mode 100644 res/scene01_vs_basic.glsl create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/res/scene01_fs_colorfultest.glsl b/res/scene01_fs_colorfultest.glsl new file mode 100644 index 0000000..15e33a1 --- /dev/null +++ b/res/scene01_fs_colorfultest.glsl @@ -0,0 +1,5 @@ +#version 330 core +out vec3 color; +void main(){ + color = vec3(1,0,0); +} diff --git a/res/scene01_vs_basic.glsl b/res/scene01_vs_basic.glsl new file mode 100644 index 0000000..6f7c56f --- /dev/null +++ b/res/scene01_vs_basic.glsl @@ -0,0 +1,12 @@ +#version 330 core + +// Input vertex data, different for all executions of this shader. +layout(location = 0) in vec3 vertexPosition_modelspace; + +// Values that stay constant for the whole mesh. +uniform mat4 MVP; + +void main(){ + // Output position of the vertex, in clip space : MVP * position + gl_Position = MVP * vec4(vertexPosition_modelspace,1); +} diff --git a/src/Makefile.am b/src/Makefile.am index d9f8a72..b7acbeb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ bin_PROGRAMS = demoscene-eo -demoscene_eo_SOURCES = demoscene-eo.c scene00.c scene01.c scene02.c +demoscene_eo_SOURCES = demoscene-eo.c utils.c scene00.c scene01.c scene02.c server-local: demoscene-eo xterm -e $(SHELL) -c "sleep 1; nc -v localhost 51914; exec $(SHELL)" & diff --git a/src/demoscene-eo.c b/src/demoscene-eo.c index ed6fe1b..1c532be 100644 --- a/src/demoscene-eo.c +++ b/src/demoscene-eo.c @@ -159,7 +159,7 @@ int parent() { case 2: res = scene02_init_caca(&shm->ge, &shm->s02e); break; } // If scene init fail, skip to the next one - if (res) SCENE_NEXT; else lastscene = shm->scene; + if (res) { printf("scene%02i_init_caca() returned %i\n", shm->scene, res); SCENE_NEXT; } else lastscene = shm->scene; } shm->ge.sdl_ticks = SDL_GetTicks(); // This value wraps if the program runs for more than ~49 days @@ -288,7 +288,7 @@ int worker_sdl() { case 2: res = scene02_init_sdl(&shm->ge, &shm->s02e); break; } // If scene init fail, skip to the next one - if (res) SCENE_NEXT; else lastscene = shm->scene; + if (res) { printf("scene%02i_init_sdl() returned %i\n", shm->scene, res); SCENE_NEXT; } else lastscene = shm->scene; } // Compute current scene frame (sdl part) switch(shm->scene) { @@ -413,7 +413,7 @@ int worker_gl() { case 2: res = scene02_init_gl(&shm->ge, &shm->s02e); break; } // If scene init fail, skip to the next one - if (res) SCENE_NEXT; else lastscene = shm->scene; + if (res) { printf("scene%02i_init_gl() returned %i\n", shm->scene, res); SCENE_NEXT; } else lastscene = shm->scene; } // Compute current scene frame (gl part) diff --git a/src/scene01.c b/src/scene01.c index a93aa3d..05457bc 100644 --- a/src/scene01.c +++ b/src/scene01.c @@ -18,55 +18,9 @@ * along with demoscene-eo. If not, see */ #include "scene01.h" +#include "utils.h" // Mostly inspired by CC0 https://gist.github.com/koute/7391344 -typedef float t_mat4x4[16]; - -static inline void mat4x4_ortho(t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar) -{ - #define T(a, b) (a * 4 + b) - - out[T(0,0)] = 2.0f / (right - left); - out[T(0,1)] = 0.0f; - out[T(0,2)] = 0.0f; - out[T(0,3)] = 0.0f; - - out[T(1,1)] = 2.0f / (top - bottom); - out[T(1,0)] = 0.0f; - out[T(1,2)] = 0.0f; - out[T(1,3)] = 0.0f; - - out[T(2,2)] = -2.0f / (zfar - znear); - out[T(2,0)] = 0.0f; - out[T(2,1)] = 0.0f; - out[T(2,3)] = 0.0f; - - out[T(3,0)] = -(right + left) / (right - left); - out[T(3,1)] = -(top + bottom) / (top - bottom); - out[T(3,2)] = -(zfar + znear) / (zfar - znear); - out[T(3,3)] = 1.0f; - - #undef T -} - -static const char * vertex_shader = - "#version 130\n" - "in vec2 i_position;\n" - "in vec4 i_color;\n" - "out vec4 v_color;\n" - "uniform mat4 u_projection_matrix;\n" - "void main() {\n" - " v_color = i_color;\n" - " gl_Position = u_projection_matrix * vec4(i_position, 0.0, 1.0);\n" - "}\n"; - -static const char * fragment_shader = - "#version 130\n" - "in vec4 v_color;\n" - "out vec4 o_color;\n" - "void main() {\n" - " o_color = v_color;\n" - "}\n"; typedef enum t_attrib_id { @@ -81,29 +35,29 @@ int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { TRACE("call"); vs = glCreateShader(GL_VERTEX_SHADER); - fs = glCreateShader(GL_FRAGMENT_SHADER); + status = gl_compile_shader_from_file(vs, "res/scene01_vs_basic.glsl"); if (status) return 40+status; - int length = strlen(vertex_shader); - glShaderSource(vs, 1, (const GLchar **)&vertex_shader, &length); - glCompileShader(vs); - - glGetShaderiv(vs, GL_COMPILE_STATUS, &status); - if(status == GL_FALSE) return 40; - - length = strlen(fragment_shader); - glShaderSource(fs, 1, (const GLchar **)&fragment_shader, &length); - glCompileShader(fs); - - glGetShaderiv(fs, GL_COMPILE_STATUS, &status); - if(status == GL_FALSE) return 41; + fs = glCreateShader(GL_FRAGMENT_SHADER); + status = gl_compile_shader_from_file(fs, "res/scene01_fs_colorfultest.glsl"); if (status) return 50+status; program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); - glBindAttribLocation(program, attrib_position, "i_position"); glBindAttribLocation(program, attrib_color, "i_color"); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &status); + + glDetachShader(program, vs); + glDetachShader(program, fs); + glDeleteShader(vs); + glDeleteShader(fs); + + if(status == GL_FALSE) { + gl_trace_shader_or_program_log(program); + return 60; + } glUseProgram(program); @@ -171,7 +125,7 @@ int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); t_mat4x4 projection_matrix; - mat4x4_ortho(projection_matrix, 0.0f, (float)FBUF_W, (float)FBUF_H, 0.0f, 0.0f, 100.0f); + gl_mat4x4_ortho(projection_matrix, 0.0f, (float)FBUF_W, (float)FBUF_H, 0.0f, 0.0f, 100.0f); glUniformMatrix4fv(glGetUniformLocation(program, "u_projection_matrix"), 1, GL_FALSE, projection_matrix); diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..a3c878e --- /dev/null +++ b/src/utils.c @@ -0,0 +1,114 @@ +#include "utils.h" + +// Mostly inspired by CC0 https://gist.github.com/koute/7391344 +void gl_mat4x4_ortho(t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar) +{ + #define T(a, b) (a * 4 + b) + + out[T(0,0)] = 2.0f / (right - left); + out[T(0,1)] = 0.0f; + out[T(0,2)] = 0.0f; + out[T(0,3)] = 0.0f; + + out[T(1,1)] = 2.0f / (top - bottom); + out[T(1,0)] = 0.0f; + out[T(1,2)] = 0.0f; + out[T(1,3)] = 0.0f; + + out[T(2,2)] = -2.0f / (zfar - znear); + out[T(2,0)] = 0.0f; + out[T(2,1)] = 0.0f; + out[T(2,3)] = 0.0f; + + out[T(3,0)] = -(right + left) / (right - left); + out[T(3,1)] = -(top + bottom) / (top - bottom); + out[T(3,2)] = -(zfar + znear) / (zfar - znear); + out[T(3,3)] = 1.0f; + + #undef T +} + +// Mostly inspired from https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_02 + +// Store all the file's contents in memory, useful to pass shaders source code to OpenGL. +const GLchar* gl_shaderfile_read(const char* path, Sint64 *out_fsize) { + GLchar *buf, *cursor; + SDL_RWops *rw; + Sint64 fsize; + size_t read; + + rw = SDL_RWFromFile(path, "rb"); if (rw == NULL) return NULL; + fsize = SDL_RWsize(rw); if (fsize == -1) return NULL; + buf = malloc(fsize+1); if (buf == NULL) return NULL; + + cursor = buf; + read = 0; + do { + cursor += read; + // Read at most to the end of buf + read = SDL_RWread(rw, cursor, 1, (fsize - (cursor-buf))); + } while ( read > 0 ); + *cursor = '\0'; // Where the +1 is used from malloc() call + + SDL_RWclose(rw); + + // Check if we have read the whole thing + if ( (cursor-buf) != fsize) { + free(buf); + return NULL; + } + + if (out_fsize != NULL) *out_fsize = fsize; + return buf; +} + +/** + * Display compilation errors from the OpenGL shader compiler + */ +void gl_trace_shader_or_program_log(GLuint object) { + GLint log_length = 0; + char *log; + + if (glIsShader(object)) { + glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length); + } else if (glIsProgram(object)) { + glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length); + } else { + TRACE("not a shader or a program"); + return; + } + + log = (char*)malloc(log_length); + if ( log == NULL ) { + TRACE("malloc failed"); + return; + } + + if (glIsShader(object)) + glGetShaderInfoLog(object, log_length, NULL, log); + else if (glIsProgram(object)) + glGetProgramInfoLog(object, log_length, NULL, log); + + TRACE(log); + free(log); +} + +GLint gl_compile_shader_from_file(GLuint shader, const char* path) { + Sint64 fsize; + GLint gl_fsize, status; + + const GLchar *source = gl_shaderfile_read(path, &fsize); + if (source == NULL) return 1; + + gl_fsize = (GLint) fsize; + glShaderSource(shader, 1, &source, &gl_fsize); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + if(status == GL_FALSE) { + gl_trace_shader_or_program_log(shader); + return 2; + } + + return 0; +} + diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..586e152 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,13 @@ +#ifndef UTILS_H_INCLUDED +#define UTILS_H_INCLUDED + +#include "main.h" + +typedef float t_mat4x4[16]; +void gl_mat4x4_ortho(t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar); + +const GLchar* gl_shaderfile_read(const char* path, Sint64 *out_fsize); +void gl_trace_shader_or_program_log(GLuint object); +GLint gl_compile_shader_from_file(GLuint shader, const char* path); + +#endif -- cgit v1.2.3