shader_t compile_gl_shader(u32 type, char **src) { shader_t shader = {0}; shader.id = glCreateShader(type); glShaderSource(shader.id, 1, (const char **)src, 0); glCompileShader(shader.id); i32 status; glGetShaderiv(shader.id, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) glGetShaderInfoLog(shader.id, MAX_SHADER_LOG, 0, shader.log); else snprintf(shader.log, MAX_SHADER_LOG, "compiled successfully"); return shader; } shader_t compile_gl_shader_file(u32 type, const char *filename) { char *src; shader_t shader = {0}; arena_t tmp = alloc_arena(0); if (!sys_read_file(&tmp, &src, filename)) { printf("error: failed to read: \"%s\"\n", filename); release_arena(&tmp); return shader; } shader = compile_gl_shader(type, &src); release_arena(&tmp); if (!shader.id) printf("error: \"%s\": ", filename); else printf("info: \"%s\": ", filename); printf("%s", shader.log); printf("\n"); return shader; } shader_t load_gl_shader(const char *dir, const char *vert_filename, const char *geom_filename, const char *frag_filename) { shader_t shader = {0}; shader.id = glCreateProgram(); char full_path[MAX_PATH]; shader_t vert; if (vert_filename) { snprintf(full_path, sizeof(full_path), "%s/%s", dir, vert_filename); vert = compile_gl_shader_file(GL_VERTEX_SHADER, full_path); glAttachShader(shader.id, vert.id); } shader_t geom; if (geom_filename) { snprintf(full_path, sizeof(full_path), "%s/%s", dir, geom_filename); geom = compile_gl_shader_file(GL_GEOMETRY_SHADER, full_path); glAttachShader(shader.id, geom.id); } shader_t frag; if (frag_filename) { snprintf(full_path, sizeof(full_path), "%s/%s", dir, frag_filename); frag = compile_gl_shader_file(GL_FRAGMENT_SHADER, full_path); glAttachShader(shader.id, frag.id); } i32 status; glLinkProgram(shader.id); glGetProgramiv(shader.id, GL_LINK_STATUS, &status); if (status == GL_FALSE) { glGetProgramInfoLog(shader.id, MAX_SHADER_LOG, 0, shader.log); printf("error: failed to link shader program:\n%s", shader.log); } else { printf("info: shader linked successfuly\n\n"); } if (vert_filename) glDeleteShader(vert.id); if (geom_filename) glDeleteShader(geom.id); if (frag_filename) glDeleteShader(frag.id); return shader; } void shader_set_v3(shader_t shader, const char *name, v3 vec) { i32 location = glGetUniformLocation(shader.id, name); glUniform3fv(location, 1, (f32 *)&vec); } void shader_set_v4(shader_t shader, const char *name, v4 vec) { i32 location = glGetUniformLocation(shader.id, name); glUniform4fv(location, 1, (f32 *)&vec); } void shader_set_mat4(shader_t shader, const char *name, mat4 mat) { i32 location = glGetUniformLocation(shader.id, name); glUniformMatrix4fv(location, 1, 0, (f32 *)&mat); }