diff options
Diffstat (limited to 'src/shader.c')
-rw-r--r-- | src/shader.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/shader.c b/src/shader.c new file mode 100644 index 0000000..d6f1e37 --- /dev/null +++ b/src/shader.c @@ -0,0 +1,109 @@ +#include "shader.h" +#include <stdio.h> + +static GLuint create_shader(GLenum shader_type, const char *src); +static GLuint create_program(GLuint vertex_shader, GLuint fragment_shader); + +int +shader_init(Shader *s, const char *vertex_src, const char *fragment_src) +{ + const GLuint vertex_shader = create_shader(GL_VERTEX_SHADER, vertex_src); + if (vertex_shader == 0) { + fprintf(stderr, "create_shader vertex failed\n"); + return -1; + } + + const GLuint fragment_shader = create_shader(GL_FRAGMENT_SHADER, fragment_src); + if (fragment_shader == 0) { + fprintf(stderr, "create_shader fragment failed\n"); + glDeleteShader(vertex_shader); + return -1; + } + + const GLuint program = create_program(vertex_shader, fragment_shader); + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + if (program == 0) { + fprintf(stderr, "create_program failed\n"); + return -1; + } + + s->id = program; + return 0; +} + +void +shader_deinit(Shader *s) +{ + if (s->id) { + glDeleteProgram(s->id); + s->id = 0; + } +} + +void +shader_use(const Shader *s) +{ + glUseProgram(s->id); +} + +int +shader_uniform_location(const Shader *s, const char *name) +{ + const GLint location = glGetUniformLocation(s->id, name); + if (location < -1) { + fprintf(stderr, "glGetUniformLocation failed with '%s'\n", name); + return -1; + } + return location; +} + +static GLuint +create_shader(GLenum shader_type, const char *src) +{ + const GLuint shader = glCreateShader(shader_type); + if (shader == 0) { + fprintf(stderr, "glCreateShader failed\n"); + return 0; + } + glShaderSource(shader, 1, &src, NULL); + glCompileShader(shader); + + int success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (!success) { + char info_log[512]; + glGetShaderInfoLog(shader, 512, NULL, info_log); + fprintf(stderr, "glCompileShader failed:\n%s\n", info_log); + glDeleteShader(shader_type); + return 0; + } + + return shader; +} + +static GLuint +create_program(GLuint vertex_shader, GLuint fragment_shader) +{ + const GLuint program = glCreateProgram(); + if (program == 0) { + fprintf(stderr, "glCreateProgram failed\n"); + return 0; + } + + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + glLinkProgram(program); + + int success; + glGetProgramiv(program, GL_LINK_STATUS, &success); + if (!success) { + char info_log[512]; + glGetProgramInfoLog(program, 512, NULL, info_log); + fprintf(stderr, "glLinkProgram failed:\n%s\n", info_log); + glDeleteProgram(program); + return 0; + } + + return program; +} |