diff options
Diffstat (limited to 'src/gunner/shader_sys.c')
| -rw-r--r-- | src/gunner/shader_sys.c | 140 |
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 |
