Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/shader.h
2025-09-02 14:43:36 +02:00

327 lines
8.7 KiB
C

uint shd_compile(const char* vcode, const char* fcode, uint vlen, uint flen, const char* vertex, const char* fragment, const char* inc) {
int ok;
uint vs, fs, pr;
char *logstr = sys.work_buf;
const char *code[3];
uint len[3];
code[0] = "#version " SHD_VERSION "\n";
len[0] = strlen(code[0]);
vs = glCreateShader(GL_VERTEX_SHADER);
code[1] = inc;
code[2] = vcode;
len[1] = strlen(inc);
len[2] = vlen;
glShaderSource(vs, 3, code, len);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
if(!ok) {
glGetShaderInfoLog(vs, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EVERTEX, vertex);
glDeleteShader(vs);
return 0;
}
fs = glCreateShader(GL_FRAGMENT_SHADER);
code[1] = inc;
code[2] = fcode;
len[1] = strlen(inc);
len[2] = flen;
glShaderSource(fs, 3, code, len);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
if(!ok) {
glGetShaderInfoLog(fs, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EFRAGMENT, fragment);
glDeleteShader(vs);
glDeleteShader(fs);
return 0;
}
pr = glCreateProgram();
glAttachShader(pr, vs);
glAttachShader(pr, fs);
glLinkProgram(pr);
glGetProgramiv(pr, GL_LINK_STATUS, &ok);
if(!ok) {
glGetProgramInfoLog(pr, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EPROGRAM, vertex, fragment);
glDeleteShader(vs);
glDeleteShader(fs);
glDeleteProgram(pr);
return 0;
}
glDeleteShader(vs);
glDeleteShader(fs);
return pr;
}
/*
void shd_delete(uint *id) {
if(*id) {
glDeleteProgram(*id);
logd(LOG_GFX, STR_SHD_IUNLOADED, *id);
*id = 0;
}
}
*/
uint shd_load_files(const char* vertex, const char* fragment, const char* inc) {
byte *vcode;
byte *fcode;
int ok;
uint prog;
uint vsize, fsize;
vsize = file_read(&vcode, vertex);
if(!vsize) {
// loge(LOG_GFX, STR_SHD_ELOADVERT, vertex);
return 0;
}
fsize = file_read(&fcode, fragment);
if(!fsize) {
// loge(LOG_GFX, STR_SHD_ELOADFRAG, fragment);
mem_free(vcode);
return 0;
}
prog = shd_compile(vcode, fcode, vsize, fsize, vertex, fragment, inc);
mem_free(vcode);
mem_free(fcode);
return prog;
}
byte shd_unload(shd_t *shd) {
if(!(shd->id)) {
return 0;
}
glDeleteProgram(shd->id);
// if(shd->builtin)
// logd(LOG_GFX, STR_SHD_IUNLOADED, shd->id);
// else
logd(LOG_GFX, STR_SHD_UNLOADED, shd->vpath, shd->fpath, shd->id);
shd->id = 0;
return 1;
}
void shd_remove(shd_t *shd) {
if(shd_unload(shd)) { // && (shd->builtin ^ 1)) {
// tbl_pop(&gdr.shaders, shd);
gdr.shd_loaded -= 1;
}
}
// byte shd_remove_sel(shd_t *shd) {
// if(shd->builtin ^ 1) {
// shd_unload(shd);
// gdr.shd_loaded -= 1;
// return 1;
// }
// return 0;
// }
int shd_clear() {
return tbl_clear_func(&gdr.shaders, (clear_func*)shd_remove);
}
// int shd_clear() {
// return tbl_clear_func_sel(&gdr.shaders, (clear_sfunc*)shd_remove_sel, gdr.shd_loaded);
// }
void shd_sel(shd_t *shader, void *draw) {
if(gdr.shader != shader->id) {
glUseProgram(gdr.shader = shader->id);
if(shader->draw)
shader->draw(draw);
}
}
/*
byte shd_load(uint *shader, const char *vpath, const char *fpath, shd_func *init, shd_func *draw) {
shd_t *bind;
// if(!((
*shader = shd_load_files(vpath, fpath, gdr.shd_include);
// )) {
// *shader = 0;
// return 0;
// }
sys_assert(bind = (shd_t*)tbl_push(&gdr.shaders));
bind->vpath = vpath;
bind->fpath = fpath;
bind->id = shader;
bind->init = init;
bind->draw = draw;
bind->builtin = 0;
shd_sel(*shader);
if(bind->init)
bind->init();
gdr.shd_loaded += 1;
logd(LOG_GFX, STR_SHD_LOADED, vpath, fpath, *shader);
return 1;
}
*/
byte shd_load(shd_t **shader, const char* vpath, const char* fpath, shd_func *init, shd_dfunc *draw) {
uint id;
shd_t *bind;
// id = shd_compile(vcode, fcode, strlen(vcode), strlen(fcode), name, name, gdr.shd_include);
id = shd_load_files(vpath, fpath, gdr.shd_include);
if(!id) {
*shader = NULL;
return 0;
}
sys_assert(bind = (shd_t*)tbl_push(&gdr.shaders));
bind->vpath = vpath;
bind->fpath = fpath;
bind->id = id;
bind->init = init;
bind->draw = draw;
// bind->builtin = 1;
glUseProgram(gdr.shader = id);
if(bind->init)
bind->init();
logd(LOG_GFX, STR_SHD_LOADED, vpath, fpath, id);
*shader = bind;
gdr.shader = 0;
gdr.shd_loaded += 1;
return 1;
}
byte shd_reload(shd_t *shader) {
uint sh;
if(sh = // (shader->builtin ? shd_compile(shader->vpath, shader->fpath, strlen(shader->vpath), strlen(shader->fpath), "[builtin]", "[builtin]", gdr.shd_include):
shd_load_files(shader->vpath, shader->fpath, gdr.shd_include)) {
glUseProgram(gdr.shader = sh);
if(shader->init)
shader->init();
// if(shader->builtin)
// logd(LOG_GFX, STR_SHD_IREASSIGN, shader->id, sh);
// else
logd(LOG_GFX, STR_SHD_REASSIGN, shader->vpath, shader->fpath, shader->id, sh);
shd_unload(shader);
shader->id = sh;
return 1;
}
return 0;
}
#define SHD_SETFNC(fn, sf, vt) void fn(const char *name, vt value) { sf(glGetUniformLocation(gdr.shader, name), value); }
#define SHD_SETFNCV(fn, sf, vt) void fn(const char *name, vt vec) { sf(glGetUniformLocation(gdr.shader, name), 1, &vec[0]); }
#define SHD_SETFNCM(fn, sf, vt) void fn(const char *name, vt mat) { sf(glGetUniformLocation(gdr.shader, name), 1, GL_FALSE, &mat[0][0]); }
#define SHD_SETFNC2(fn, sf, vt) void fn(const char *name, vt x, vt y) { sf(glGetUniformLocation(gdr.shader, name), x, y); }
#define SHD_SETFNC3(fn, sf, vt) void fn(const char *name, vt x, vt y, vt z) { sf(glGetUniformLocation(gdr.shader, name), x, y, z); }
#define SHD_SETFNC4(fn, sf, vt) void fn(const char *name, vt x, vt y, vt z, vt w) { sf(glGetUniformLocation(gdr.shader, name), x, y, z, w); }
SHD_SETFNC(shd_bool, glUniform1i, byte);
SHD_SETFNC(shd_int, glUniform1i, int);
SHD_SETFNC(shd_float, glUniform1f, float);
SHD_SETFNCV(shd_vec2, glUniform2fv, vec2);
SHD_SETFNCV(shd_vec3, glUniform3fv, vec3);
SHD_SETFNCV(shd_vec4, glUniform4fv, vec4);
SHD_SETFNC2(shd_vec2v, glUniform2f, float);
SHD_SETFNC3(shd_vec3v, glUniform3f, float);
SHD_SETFNC4(shd_vec4v, glUniform4f, float);
SHD_SETFNCM(shd_mat2, glUniformMatrix2fv, mat2);
SHD_SETFNCM(shd_mat3, glUniformMatrix3fv, mat3);
SHD_SETFNCM(shd_mat4, glUniformMatrix4fv, mat4);
void shd_color(const char *name, uint color) {
glUniform4f(glGetUniformLocation(gdr.shader, name),
(float)((uint)((color >> 16) & 0xff)) / 255.0f, (float)((uint)((color >> 8) & 0xff)) / 255.0f,
(float)((uint)(color & 0xff)) / 255.0f, (float)((uint)((color >> 24) & 0xff)) / 255.0f
);
}
void shd_scolor(const char *name, uint color) {
glUniform3f(glGetUniformLocation(gdr.shader, name),
(float)((uint)((color >> 16) & 0xff)) / 255.0f, (float)((uint)((color >> 8) & 0xff)) / 255.0f,
(float)((uint)(color & 0xff)) / 255.0f
);
}
void shd_setint(int *pos, const char *vardef, int value) {
*pos += sprintf(&gdr.shd_include[*pos], "#define %s %d\n", vardef, value);
}
void shd_setvars() {
int pos = 0;
shd_setint(&pos, "MAX_LIGHTS", gdr.light_max < 1 ? 1 : gdr.light_max);
}
int shd_refresh() {
int done = 0;
ulong iter = 0;
shd_t *shd;
shd_setvars();
while(shd = tbl_iter(&gdr.shaders, &iter)) {
done += (int)shd_reload(shd);
}
// shd_setup();
logd(LOG_GFX, STR_SHD_REFRESH, done);
return done;
}
/*
byte shd_compile_int(uint *shader, const char* name, const char* vcode, const char* fcode) {
uint pr = shd_compile(vcode, fcode, strlen(vcode), strlen(fcode), name, name, gdr.shd_include);
if(!pr)
return 0;
/*
int ok;
uint vs, fs, pr;
char *logstr = sys.work_buf;
const char *code[2];
uint len[2];
*shader = 0;
code[0] = "#version " SHD_VERSION "\n";
len[0] = strlen(code[0]);
vs = glCreateShader(GL_VERTEX_SHADER);
code[1] = vcode;
len[1] = strlen(vcode);
glShaderSource(vs, 2, code, len);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
if(!ok) {
glGetShaderInfoLog(vs, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EIVERTEX, name);
glDeleteShader(vs);
return 0;
}
fs = glCreateShader(GL_FRAGMENT_SHADER);
code[1] = fcode;
len[1] = strlen(fcode);
glShaderSource(fs, 2, code, len);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
if(!ok) {
glGetShaderInfoLog(fs, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EIFRAGMENT, name);
glDeleteShader(vs);
glDeleteShader(fs);
return 0;
}
pr = glCreateProgram();
glAttachShader(pr, vs);
glAttachShader(pr, fs);
glLinkProgram(pr);
glGetProgramiv(pr, GL_LINK_STATUS, &ok);
if(!ok) {
glGetProgramInfoLog(pr, SHD_TRACE_SIZE, NULL, logstr);
loge(LOG_GFX, "%s", logstr);
loge(LOG_GFX, STR_SHD_EIPROGRAM, name);
glDeleteShader(vs);
glDeleteShader(fs);
glDeleteProgram(pr);
return 0;
}
glDeleteShader(vs);
glDeleteShader(fs);
**** ////
*shader = pr;
shd_sel(pr);
shd_int("tex", 0);
logd(LOG_GFX, STR_SHD_ILOADED, name, pr);
return 1;
}
*/