1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#include "utils.h"
#include "config.h"
#include "text.h"
#include <stdlib.h>
#include <stdio.h>
#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);
}
}
|