328 lines
8.7 KiB
C
328 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;
|
||
|
}
|
||
|
*/
|