aboutsummaryrefslogtreecommitdiff
path: root/src/gunner/shader_sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gunner/shader_sys.c')
-rw-r--r--src/gunner/shader_sys.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/gunner/shader_sys.c b/src/gunner/shader_sys.c
new file mode 100644
index 0000000..d274966
--- /dev/null
+++ b/src/gunner/shader_sys.c
@@ -0,0 +1,140 @@
+// Defines
+
+#define MAX_SHADER_SIZE 8
+
+static const s8 version_st = String("#version 330\n");
+static const s8 type_markers[2] = {String("#define VERTEX_SHADER 1\n"), String("#define FRAG_SHADER 1\n")};
+static const s8 line_st = String("#line 1\n");
+
+// Internal Functions //
+
+// TODO: Compute?
+// Would probably require a different path altogther
+// due to how those shaders are compiled tho
+typedef enum{
+ VERTEX = 0,
+ FRAGMENT = 1
+}ShaderStep;
+
+// This returns *allocated* memory,
+// should be manually free()'ed or some kind of arena used.
+static s8 shader_block_preprocess(const s8 source, const ShaderStep shader_step)
+{
+ size total = version_st.len + type_markers[shader_step].len + line_st.len + source.len;
+
+ s8 parsed_total = create_s8(total + NULL_TERM_SZ);
+
+ size cursor = 0;
+ add_s8(parsed_total, version_st, &cursor);
+ add_s8(parsed_total, type_markers[shader_step], &cursor);
+ add_s8(parsed_total, line_st, &cursor);
+ add_s8(parsed_total, source, &cursor);
+ parsed_total.buf[cursor] = NULL_TERM;
+
+ return parsed_total;
+}
+
+static Shader load_joined_shader(const s8 path)
+{
+ Shader something = (Shader){0};
+
+ s8 file = load_file_text(path);
+ if(file.len == 0)
+ goto oops;
+
+ s8 vs = shader_block_preprocess(file, VERTEX);
+ s8 fs = shader_block_preprocess(file, FRAGMENT);
+
+ something = LoadShaderFromMemory((const char*)vs.buf, (const char*)fs.buf);
+
+ free_s8(&fs);
+ free_s8(&vs);
+
+ free_s8(&file);
+
+oops:
+ return something;
+}
+
+// Exposed Functions //
+
+static Shader shader_slots[MAX_SHADER_SIZE] = {0};
+static i32 shader_modtimes[MAX_SHADER_SIZE] = {0};
+static s8 shader_paths[MAX_SHADER_SIZE] = {0};
+
+void init_shader_sys(void)
+{
+ for(i32 i = 0; i < MAX_SHADER_SIZE; ++i){
+ shader_modtimes[i] = BLANK_DEFAULT;
+ }
+}
+
+i32 load_new_shader(const char* path)
+{
+ s8 path_str = cstr_to_s8(path);
+
+ i32 current_idx = BLANK_DEFAULT;
+ for(i32 i = 0; i < MAX_SHADER_SIZE; ++i){
+ if(equal_s8(path_str, shader_paths[current_idx])){
+ free_s8(&path_str);
+ return i;
+ }
+
+ if(shader_slots[i].id <= 0){
+ current_idx = i;
+ shader_slots[current_idx] = load_joined_shader(path_str);
+ shader_modtimes[current_idx] = GetFileModTime((const char*)path_str.buf);
+ shader_paths[current_idx] = path_str;
+ break;
+ }
+ }
+
+ //TODO: Handle slots a bit better.
+ assert(current_idx != BLANK_DEFAULT);
+
+ return current_idx;
+}
+
+void set_active_shader(i32 idx)
+{
+ assert(idx >= 0 && idx < MAX_SHADER_SIZE);
+ BeginShaderMode(shader_slots[idx]);
+}
+
+void update_shaders(void)
+{
+ for(i32 i = 0; i < MAX_SHADER_SIZE; ++i){
+ if(shader_slots[i].id > 0){
+ i32 current_mod = GetFileModTime((const char*)shader_paths[i].buf);
+
+ if(current_mod != shader_modtimes[i]){
+ shader_modtimes[i] = current_mod;
+
+ UnloadShader(shader_slots[i]);
+ shader_slots[i] = load_joined_shader(shader_paths[i]);
+ }
+ }
+ }
+}
+
+void reset_active_shader(void)
+{
+ EndShaderMode();
+}
+
+void unload_shader(i32 idx)
+{
+ assert(idx >= 0 && idx < MAX_SHADER_SIZE);
+
+ UnloadShader(shader_slots[idx]);
+ shader_modtimes[idx] = BLANK_DEFAULT;
+ free_s8(&shader_paths[idx]);
+}
+
+void unload_active_shaders(void)
+{
+ for(i32 i = 0; i < MAX_SHADER_SIZE; ++i){
+ if(shader_slots[i].id > 0)
+ unload_shader(i);
+ }
+} \ No newline at end of file