#include "shader.hpp" #include "common.hpp" #include "vendor/glad/glad.h" #include "defer.hpp" #include #include #include #include unsigned int create_shader(unsigned int type, const char **source) { unsigned int shader = glCreateShader(type); if (!shader) { printf("err: create_shader: glCreateShader returned 0\n"); return 0; } glShaderSource(shader, 1, source, NULL); glCompileShader(shader); int success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { char log[512]; glGetShaderInfoLog(shader, 512, NULL, log); printf("err: create_shader: compilation failed, log: %s\n", log); return 0; } return shader; } unsigned int create_program_source(const char *vertex_shader_source, const char *fragment_shader_source) { unsigned int program = glCreateProgram(); if (!program) { printf("err: create_program: glCreateProgram returned 0\n"); return 0; } unsigned int vertex_shader = create_shader(GL_VERTEX_SHADER, &vertex_shader_source); if (!vertex_shader) { printf("err: create_program: create_shader failed returned 0 (vertex_shader)\n"); return 0; } unsigned int fragment_shader = create_shader(GL_FRAGMENT_SHADER, &fragment_shader_source); if (!fragment_shader) { printf("err: create_program: create_shader failed returned 0 (fragment_shader)\n"); return 0; } glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); glLinkProgram(program); int success; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { char log[512]; glGetProgramInfoLog(program, 512, NULL, log); printf("err: create_program: link failed, log: %s\n", log); return 0; } return program; } unsigned int create_program(const char *vertex_shader_path, const char *fragment_shader_path) { Errno err = 0; FILE *vertex_shader_file = fopen(vertex_shader_path, "r"); defer(if (vertex_shader_file) fclose(vertex_shader_file)); if (!vertex_shader_file) { fprintf(stderr, "create_program: failed to open vertex shader file (%s): %s\n", vertex_shader_path, strerror(errno)); return 0; } char *vertex_shader_source = NULL; defer(free(vertex_shader_source)); err = read_entire_file(vertex_shader_file, &vertex_shader_source, true); if (err) { fprintf(stderr, "create_program: failed to read vertex shader file (%s): %s\n", vertex_shader_path, strerror(err)); return 0; } FILE *fragment_shader_file = fopen(fragment_shader_path, "r"); defer(if (fragment_shader_file) fclose(fragment_shader_file)); if (!fragment_shader_file) { fprintf(stderr, "create_program: failed to open fragment shader file (%s): %s\n", fragment_shader_path, strerror(errno)); return 0; } char *fragment_shader_source = NULL; defer(free(fragment_shader_source)); err = read_entire_file(fragment_shader_file, &fragment_shader_source, true); if (err) { fprintf(stderr, "create_program: failed to read fragment shader file (%s): %s\n", fragment_shader_path, strerror(err)); return 0; } return create_program_source(vertex_shader_source, fragment_shader_source); } void program_set(unsigned int program, const char *uniform, int value) { glUniform1i(glGetUniformLocation(program, uniform), value); } void program_set(unsigned int program, const char *uniform, unsigned int value) { glUniform1ui(glGetUniformLocation(program, uniform), value); } void program_set(unsigned int program, const char *uniform, float value) { glUniform1f(glGetUniformLocation(program, uniform), value); } void program_set(unsigned int program, const char *uniform, glm::vec3 vec) { glUniform3fv(glGetUniformLocation(program, uniform), 1, &vec[0]); } void program_set(unsigned int program, const char *uniform, float x, float y, float z) { glUniform3f(glGetUniformLocation(program, uniform), x, y, z); } void program_set(unsigned int program, const char *uniform, const glm::mat4 &mat) { glUniformMatrix4fv(glGetUniformLocation(program, uniform), 1, GL_FALSE, &mat[0][0]); }