summaryrefslogtreecommitdiff
path: root/src/shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader.c')
-rw-r--r--src/shader.c109
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;
+}