#include "shader.h" #include "sys.h" #include #include #include #include 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_i32(u32 id, const char *name, i32 v) { u32 loc = glGetUniformLocation(id, name); glUniform1i(loc, v); } void uniform_v2(u32 id, const char *name, v2 v) { u32 loc = glGetUniformLocation(id, name); glUniform2fv(loc, 1, (const f32 *)&v); } void uniform_v3(u32 id, const char *name, v3 v) { u32 loc = glGetUniformLocation(id, name); glUniform3fv(loc, 1, (const f32 *)&v); } void uniform_v4(u32 id, const char *name, v4 v) { u32 loc = glGetUniformLocation(id, name); glUniform4fv(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); }