diff options
Diffstat (limited to 'in_practice/breakout/shader.c')
-rw-r--r-- | in_practice/breakout/shader.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/in_practice/breakout/shader.c b/in_practice/breakout/shader.c new file mode 100644 index 0000000..2fff3c4 --- /dev/null +++ b/in_practice/breakout/shader.c @@ -0,0 +1,101 @@ +#include "shader.h" +#include "sys.h" + +#include <GL/glew.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +shader_t shaders[MAX_SHADERS] = {0}; + +static u32 compile_shader(GLenum type, const char *dir, const char *filename) +{ + char path[512] = {0}; + snprintf(path, 512, "%s/%s", (dir ? dir : "."), filename); + const char *src = (const char *)read_entire_file(path); + if (!src) { + info("failed to read the file \"%s\"", path); + return 0; + } + u32 id = glCreateShader(type); + glShaderSource(id, 1, &src, 0); + free((void *)src); + glCompileShader(id); + i32 status; + glGetShaderiv(id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + char log[512]; + glGetShaderInfoLog(id, 512, 0, log); + info("failed to compile \"%s\"\n%s", path, log); + } else { + info("\"%s\" compiled successfully", path); + } + return id; +} + +u32 load_shader(const char *dir, const char *vertex_filename, const char *fragment_filename, const char *geometry_filename, const char *name) +{ + if (get_shader(name)) { + info("shader \"%s\" already exist", name); + return 0; + } + u32 id = glCreateProgram(); + u32 vert = compile_shader(GL_VERTEX_SHADER, dir, vertex_filename); + glAttachShader(id, vert); + u32 frag = compile_shader(GL_FRAGMENT_SHADER, dir, fragment_filename); + glAttachShader(id, frag); + u32 geom = 0; + if (geometry_filename) { + geom = compile_shader(GL_GEOMETRY_SHADER, dir, geometry_filename); + glAttachShader(id, geom); + } + glLinkProgram(id); + i32 success; + glGetProgramiv(id, GL_LINK_STATUS, &success); + if (success == GL_FALSE) { + char log[512]; + glGetProgramInfoLog(id, 512, 0, log); + info("failed to link shader:\n%s", log); + } + glDeleteShader(vert); + glDeleteShader(frag); + if (geometry_filename) + glDeleteShader(geom); + shader_t shader = {id, name}; + i32 i; + for (i = 0; i < MAX_SHADERS; i++) { + if (!shaders[i].id) { + shaders[i] = shader; + return id; + } + } + info("shader limit (%d) reached", MAX_SHADERS); + glDeleteProgram(id); + return 0; +} + +u32 get_shader(const char *name) +{ + for (i32 i = 0; i < MAX_SHADERS; i++) + if (shaders[i].name && strstr(shaders[i].name, name)) + return shaders[i].id; + return 0; +} + +void uniform_f32(u32 id, const char *name, f32 v) +{ + u32 loc = glGetUniformLocation(id, name); + glUniform1f(loc, v); +} + +void uniform_v3(u32 id, const char *name, v3 v) +{ + u32 loc = glGetUniformLocation(id, name); + glUniform3fv(loc, 1, (const f32 *)&v); +} + +void uniform_mat(u32 id, const char *name, mat m) +{ + u32 loc = glGetUniformLocation(id, name); + glUniformMatrix4fv(loc, 1, 0, (const f32 *)&m); +} |