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; } */