summaryrefslogtreecommitdiff
path: root/in_practice/breakout/shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'in_practice/breakout/shader.c')
-rw-r--r--in_practice/breakout/shader.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/in_practice/breakout/shader.c b/in_practice/breakout/shader.c
new file mode 100644
index 0000000..2fff3c4
--- /dev/null
+++ b/in_practice/breakout/shader.c
@@ -0,0 +1,101 @@
+#include "shader.h"
+#include "sys.h"
+
+#include <GL/glew.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+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_v3(u32 id, const char *name, v3 v)
+{
+ u32 loc = glGetUniformLocation(id, name);
+ glUniform3fv(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);
+}