From 0a1172b75f571685c264a8b9d8ee224bbf11381f Mon Sep 17 00:00:00 2001 From: xolatile Date: Wed, 6 Aug 2025 22:54:55 +0200 Subject: Please do not hate me, it makes sense... --- src/engine/shader.cpp | 448 +++++++++++++++----------------------------------- 1 file changed, 137 insertions(+), 311 deletions(-) (limited to 'src/engine/shader.cpp') diff --git a/src/engine/shader.cpp b/src/engine/shader.cpp index 67b9e42..8f5e9b7 100644 --- a/src/engine/shader.cpp +++ b/src/engine/shader.cpp @@ -18,41 +18,32 @@ VAR(maxvsuniforms, 1, 0, 0); VAR(maxfsuniforms, 1, 0, 0); VAR(maxvaryings, 1, 0, 0); -void loadshaders() -{ +void loadshaders() { standardshaders = true; execfile("data/glsl.cfg"); standardshaders = false; - nullshader = lookupshaderbyname("null"); hudshader = lookupshaderbyname("hud"); hudnotextureshader = lookupshaderbyname("hudnotexture"); stdworldshader = lookupshaderbyname("stdworld"); if(!nullshader || !hudshader || !hudnotextureshader || !stdworldshader) fatal("cannot find shader definitions"); - dummyslot.shader = stdworldshader; - textureshader = lookupshaderbyname("texture"); notextureshader = lookupshaderbyname("notexture"); nocolorshader = lookupshaderbyname("nocolor"); - nullshader->set(); - loadedshaders = true; } -Shader *lookupshaderbyname(const char *name) -{ +Shader *lookupshaderbyname(const char *name) { Shader *s = shaders.access(name); return s && s->loaded() ? s : NULL; } -Shader *generateshader(const char *name, const char *fmt, ...) -{ +Shader *generateshader(const char *name, const char *fmt, ...) { if(!loadedshaders) return NULL; Shader *s = name ? lookupshaderbyname(name) : NULL; - if(!s) - { + if(!s) { defvformatstring(cmd, fmt, fmt); bool wasstandard = standardshaders; standardshaders = true; @@ -64,29 +55,24 @@ Shader *generateshader(const char *name, const char *fmt, ...) return s; } -static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) -{ +static void showglslinfo(GLenum type, GLuint obj, const char *name, const char **parts = NULL, int numparts = 0) { GLint length = 0; if(type) glGetShaderiv_(obj, GL_INFO_LOG_LENGTH, &length); else glGetProgramiv_(obj, GL_INFO_LOG_LENGTH, &length); - if(length > 1) - { + if(length > 1) { conoutf(CON_ERROR, "GLSL ERROR (%s:%s)", type == GL_VERTEX_SHADER ? "VS" : (type == GL_FRAGMENT_SHADER ? "FS" : "PROG"), name); FILE *l = getlogfile(); - if(l) - { + if(l) { GLchar *log = new GLchar[length]; if(type) glGetShaderInfoLog_(obj, length, &length, log); else glGetProgramInfoLog_(obj, length, &length, log); fprintf(l, "%s\n", log); bool partlines = log[0] != '0'; int line = 0; - loopi(numparts) - { + loopi(numparts) { const char *part = parts[i]; int startline = line; - while(*part) - { + while(*part) { const char *next = strchr(part, '\n'); if(++line > 1000) goto done; if(partlines) fprintf(l, "%d(%d): ", i, line - startline); else fprintf(l, "%d: ", line); @@ -101,30 +87,26 @@ static void showglslinfo(GLenum type, GLuint obj, const char *name, const char * } } -static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) -{ +static void compileglslshader(GLenum type, GLuint &obj, const char *def, const char *name, bool msg = true) { const char *source = def + strspn(def, " \t\r\n"); const char *parts[16]; int numparts = 0; - static const struct { int version; const char * const header; } glslversions[] = - { - { 330, "#version 330\n" }, - { 150, "#version 150\n" }, - { 130, "#version 130\n" }, - { 120, "#version 120\n" } + static const struct { int version; const char * const header; } glslversions[] = { + { + 330, "#version 330\n" }, { + 150, "#version 150\n" }, { + 130, "#version 130\n" }, { + 120, "#version 120\n" } }; - loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) - { + loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version) { parts[numparts++] = glslversions[i].header; break; } - if(glslversion >= 130) - { + if(glslversion >= 130) { if(type == GL_VERTEX_SHADER) parts[numparts++] = "#define attribute in\n" "#define varying out\n"; - else if(type == GL_FRAGMENT_SHADER) - { + else if(type == GL_FRAGMENT_SHADER) { parts[numparts++] = "#define varying in\n"; if(glslversion < 150) parts[numparts++] = "precision highp float;\n"; if(glversion >= 300) parts[numparts++] = @@ -137,35 +119,30 @@ static void compileglslshader(GLenum type, GLuint &obj, const char *def, const c "#define textureCube(sampler, coords) texture(sampler, coords)\n"; } parts[numparts++] = source; - obj = glCreateShader_(type); glShaderSource_(obj, numparts, (const GLchar **)parts, NULL); glCompileShader_(obj); GLint success; glGetShaderiv_(obj, GL_COMPILE_STATUS, &success); - if(!success) - { + if(!success) { if(msg) showglslinfo(type, obj, name, parts, numparts); glDeleteShader_(obj); obj = 0; } } -static void bindglsluniform(Shader &s, UniformLoc &u) -{ +static void bindglsluniform(Shader &s, UniformLoc &u) { u.loc = glGetUniformLocation_(s.program, u.name); if(!u.blockname || !hasUBO) return; GLuint bidx = glGetUniformBlockIndex_(s.program, u.blockname); GLuint uidx = GL_INVALID_INDEX; glGetUniformIndices_(s.program, 1, &u.name, &uidx); - if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) - { + if(bidx != GL_INVALID_INDEX && uidx != GL_INVALID_INDEX) { GLint sizeval = 0, offsetval = 0, strideval = 0; glGetActiveUniformBlockiv_(s.program, bidx, GL_UNIFORM_BLOCK_DATA_SIZE, &sizeval); if(sizeval <= 0) return; glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_OFFSET, &offsetval); - if(u.stride > 0) - { + if(u.stride > 0) { glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_ARRAY_STRIDE, &strideval); if(strideval > u.stride) return; } @@ -175,69 +152,57 @@ static void bindglsluniform(Shader &s, UniformLoc &u) } } -static void linkglslprogram(Shader &s, bool msg = true) -{ +static void linkglslprogram(Shader &s, bool msg = true) { s.program = s.vsobj && s.psobj ? glCreateProgram_() : 0; GLint success = 0; - if(s.program) - { + if(s.program) { glAttachShader_(s.program, s.vsobj); glAttachShader_(s.program, s.psobj); uint attribs = 0; - loopv(s.attriblocs) - { + loopv(s.attriblocs) { AttribLoc &a = s.attriblocs[i]; glBindAttribLocation_(s.program, a.loc, a.name); attribs |= 1<= 300) - { + if(glversion >= 300) { glBindFragDataLocation_(s.program, 0, "cube2_FragColor"); } glLinkProgram_(s.program); glGetProgramiv_(s.program, GL_LINK_STATUS, &success); } - if(success) - { + if(success) { glUseProgram_(s.program); - loopi(8) - { + loopi(8) { static const char * const texnames[8] = { "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7" }; GLint loc = glGetUniformLocation_(s.program, texnames[i]); if(loc != -1) glUniform1i_(loc, i); } - loopv(s.defaultparams) - { + loopv(s.defaultparams) { SlotShaderParamState ¶m = s.defaultparams[i]; param.loc = glGetUniformLocation_(s.program, param.name); } loopv(s.uniformlocs) bindglsluniform(s, s.uniformlocs[i]); glUseProgram_(0); } - else if(s.program) - { + else if(s.program) { if(msg) showglslinfo(GL_FALSE, s.program, s.name); glDeleteProgram_(s.program); s.program = 0; } } -int getlocalparam(const char *name) -{ +int getlocalparam(const char *name) { return localparams.access(name, int(localparams.numelems)); } -static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) -{ +static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format) { int idx = getlocalparam(name); - if(idx >= s.localparamremap.length()) - { + if(idx >= s.localparamremap.length()) { int n = idx + 1 - s.localparamremap.length(); memset(s.localparamremap.pad(n), 0xFF, n); } s.localparamremap[idx] = s.localparams.length(); - LocalShaderParamState &l = s.localparams.add(); l.name = name; l.loc = loc; @@ -246,11 +211,9 @@ static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum return idx; } -GlobalShaderParamState *getglobalparam(const char *name) -{ +GlobalShaderParamState *getglobalparam(const char *name) { GlobalShaderParamState *param = globalparams.access(name); - if(!param) - { + if(!param) { param = &globalparams[name]; param->name = name; memset(param->buf, -1, sizeof(param->buf)); @@ -259,8 +222,7 @@ GlobalShaderParamState *getglobalparam(const char *name) return param; } -static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) -{ +static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format) { GlobalShaderParamUse &g = s.globalparams.add(); g.param = param; g.version = -2; @@ -270,10 +232,8 @@ static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *p return &g; } -static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) -{ - switch(format) - { +static void setglsluniformformat(Shader &s, const char *name, GLenum format, int size) { + switch(format) { case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: @@ -294,31 +254,26 @@ static void setglsluniformformat(Shader &s, const char *name, GLenum format, int return; } if(!strncmp(name, "gl_", 3)) return; - int loc = glGetUniformLocation_(s.program, name); if(loc < 0) return; - loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) - { + loopvj(s.defaultparams) if(s.defaultparams[j].loc == loc) { s.defaultparams[j].format = format; return; } loopvj(s.uniformlocs) if(s.uniformlocs[j].loc == loc) return; loopvj(s.globalparams) if(s.globalparams[j].loc == loc) return; loopvj(s.localparams) if(s.localparams[j].loc == loc) return; - name = getshaderparamname(name); GlobalShaderParamState *param = globalparams.access(name); if(param) addglobalparam(s, param, loc, size, format); else addlocalparam(s, name, loc, size, format); } -static void allocglslactiveuniforms(Shader &s) -{ +static void allocglslactiveuniforms(Shader &s) { GLint numactive = 0; glGetProgramiv_(s.program, GL_ACTIVE_UNIFORMS, &numactive); string name; - loopi(numactive) - { + loopi(numactive) { GLsizei namelen = 0; GLint size = 0; GLenum format = GL_FLOAT_VEC4; @@ -332,19 +287,16 @@ static void allocglslactiveuniforms(Shader &s) } } -void Shader::allocparams(Slot *slot) -{ - if(slot) - { -#define UNIFORMTEX(name, tmu) \ - { \ +void Shader::allocparams(Slot *slot) { + if(slot) { +#define UNIFORMTEX(name, tmu) { \ + \ loc = glGetUniformLocation_(program, name); \ int val = tmu; \ if(loc != -1) glUniform1i_(loc, val); \ } int loc, tmu = 2; - if(type & SHADER_NORMALSLMS) - { + if(type & SHADER_NORMALSLMS) { UNIFORMTEX("lmcolor", 1); UNIFORMTEX("lmdir", 2); tmu++; @@ -352,19 +304,16 @@ void Shader::allocparams(Slot *slot) else UNIFORMTEX("lightmap", 1); UNIFORMTEX("shadowmap", 7); int stex = 0; - loopv(slot->sts) - { + loopv(slot->sts) { Slot::Tex &t = slot->sts[i]; - switch(t.type) - { + switch(t.type) { case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break; case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break; case TEX_DECAL: UNIFORMTEX("decal", tmu++); break; case TEX_SPEC: if(t.combined<0) UNIFORMTEX("specmap", tmu++); break; case TEX_DEPTH: if(t.combined<0) UNIFORMTEX("depthmap", tmu++); break; case TEX_ALPHA: if(t.combined<0) UNIFORMTEX("alphamap", tmu++); break; - case TEX_UNKNOWN: - { + case TEX_UNKNOWN: { defformatstring(sname, "stex%d", stex++); UNIFORMTEX(sname, tmu++); break; @@ -377,32 +326,25 @@ void Shader::allocparams(Slot *slot) int GlobalShaderParamState::nextversion = 0; -void GlobalShaderParamState::resetversions() -{ - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { +void GlobalShaderParamState::resetversions() { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version != u.param->version) u.version = -2; } }); nextversion = 0; enumerate(globalparams, GlobalShaderParamState, g, { g.version = ++nextversion; }); - enumerate(shaders, Shader, s, - { - loopv(s.globalparams) - { + enumerate(shaders, Shader, s, { + loopv(s.globalparams) { GlobalShaderParamUse &u = s.globalparams[i]; if(u.version >= 0) u.version = u.param->version; } }); } -static inline void setslotparam(SlotShaderParamState &l, const float *val) -{ - switch(l.format) - { +static inline void setslotparam(SlotShaderParamState &l, const float *val) { + switch(l.format) { case GL_BOOL: case GL_FLOAT: glUniform1fv_(l.loc, 1, val); break; case GL_BOOL_VEC2: @@ -426,52 +368,46 @@ static inline void setslotparam(SlotShaderParamState &l, const float *val) } while(0) #define SETSLOTPARAMS(slotparams) \ - loopv(slotparams) \ - { \ + loopv(slotparams) { \ + \ SlotShaderParam &p = slotparams[i]; \ if(!defaultparams.inrange(p.loc)) continue; \ SlotShaderParamState &l = defaultparams[p.loc]; \ SETSLOTPARAM(l, unimask, p.loc, p.val); \ } #define SETDEFAULTPARAMS \ - loopv(defaultparams) \ - { \ + loopv(defaultparams) { \ + \ SlotShaderParamState &l = defaultparams[i]; \ SETSLOTPARAM(l, unimask, i, l.val); \ } -void Shader::setslotparams(Slot &slot) -{ +void Shader::setslotparams(Slot &slot) { uint unimask = 0; SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } -void Shader::setslotparams(Slot &slot, VSlot &vslot) -{ +void Shader::setslotparams(Slot &slot, VSlot &vslot) { uint unimask = 0; - if(vslot.slot == &slot) - { + if(vslot.slot == &slot) { SETSLOTPARAMS(vslot.params) SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } - else - { + else { SETSLOTPARAMS(slot.params) SETDEFAULTPARAMS } } -void Shader::bindprograms() -{ +void Shader::bindprograms() { if(this == lastshader || type&(SHADER_DEFERRED|SHADER_INVALID)) return; glUseProgram_(program); lastshader = this; } -bool Shader::compile() -{ +bool Shader::compile() { if(!vsstr) vsobj = !reusevs || reusevs->invalid() ? 0 : reusevs->vsobj; else compileglslshader(GL_VERTEX_SHADER, vsobj, vsstr, name, !variantshader); if(!psstr) psobj = !reuseps || reuseps->invalid() ? 0 : reuseps->psobj; @@ -480,8 +416,7 @@ bool Shader::compile() return program!=0; } -void Shader::cleanup(bool invalid) -{ +void Shader::cleanup(bool invalid) { detailshader = NULL; used = false; if(vsobj) { if(!reusevs) glDeleteShader_(vsobj); vsobj = 0; } @@ -490,8 +425,7 @@ void Shader::cleanup(bool invalid) localparams.setsize(0); localparamremap.setsize(0); globalparams.setsize(0); - if(standard || invalid) - { + if(standard || invalid) { type = SHADER_INVALID; DELETEA(vsstr); DELETEA(psstr); @@ -511,28 +445,24 @@ void Shader::cleanup(bool invalid) bool Shader::isnull(const Shader *s) { return !s; } -static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genattriblocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:attrib"); string name; int loc; if(reusevs) s.attriblocs = reusevs->attriblocs; - else while((vs = strstr(vs, "//:attrib"))) - { + else while((vs = strstr(vs, "//:attrib"))) { if(sscanf(vs, "//:attrib %100s %d", name, &loc) == 2) s.attriblocs.add(AttribLoc(getshaderparamname(name), loc)); vs += len; } } -static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) -{ +static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *reusevs, Shader *reuseps) { static int len = strlen("//:uniform"); string name, blockname; int binding, stride; if(reusevs) s.uniformlocs = reusevs->uniformlocs; - else while((vs = strstr(vs, "//:uniform"))) - { + else while((vs = strstr(vs, "//:uniform"))) { int numargs = sscanf(vs, "//:uniform %100s %100s %d %d", name, blockname, &binding, &stride); if(numargs >= 3) s.uniformlocs.add(UniformLoc(getshaderparamname(name), getshaderparamname(blockname), binding, numargs >= 4 ? stride : 0)); else if(numargs >= 1) s.uniformlocs.add(UniformLoc(getshaderparamname(name))); @@ -540,14 +470,11 @@ static void genuniformlocs(Shader &s, const char *vs, const char *ps, Shader *re } } -Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) -{ - if(Shader::lastshader) - { +Shader *newshader(int type, const char *name, const char *vs, const char *ps, Shader *variant = NULL, int row = 0) { + if(Shader::lastshader) { glUseProgram_(0); Shader::lastshader = NULL; } - Shader *exists = shaders.access(name); char *rname = exists ? exists->name : newstring(name); Shader &s = shaders[rname]; @@ -560,17 +487,14 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.standard = standardshaders; if(forceshaders) s.forced = true; s.reusevs = s.reuseps = NULL; - if(variant) - { + if(variant) { int row = 0, col = 0; - if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) - { + if(!vs[0] || sscanf(vs, "%d , %d", &row, &col) >= 1) { DELETEA(s.vsstr); s.reusevs = !vs[0] ? variant : variant->getvariant(col, row); } row = col = 0; - if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) - { + if(!ps[0] || sscanf(ps, "%d , %d", &row, &col) >= 1) { DELETEA(s.psstr); s.reuseps = !ps[0] ? variant : variant->getvariant(col, row); } @@ -581,8 +505,7 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh s.uniformlocs.setsize(0); genattriblocs(s, vs, ps, s.reusevs, s.reuseps); genuniformlocs(s, vs, ps, s.reusevs, s.reuseps); - if(!s.compile()) - { + if(!s.compile()) { s.cleanup(true); if(variant) shaders.remove(rname); return NULL; @@ -592,19 +515,16 @@ Shader *newshader(int type, const char *name, const char *vs, const char *ps, Sh return &s; } -void setupshaders() -{ +void setupshaders() { GLint val; glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &val); maxvsuniforms = val/4; glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &val); maxfsuniforms = val/4; - if(glversion < 300) - { + if(glversion < 300) { glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &val); maxvaryings = val; } - standardshaders = true; nullshader = newshader(0, "null", "attribute vec4 vvertex;\n" @@ -644,38 +564,31 @@ void setupshaders() " gl_FragColor = color;\n" "}\n"); standardshaders = false; - if(!nullshader || !hudshader || !hudnotextureshader) fatal("failed to setup shaders"); - dummyslot.shader = nullshader; } -static const char *findglslmain(const char *s) -{ +static const char *findglslmain(const char *s) { const char *main = strstr(s, "main"); if(!main) return NULL; for(; main >= s; main--) switch(*main) { case '\r': case '\n': case ';': return main + 1; } return s; } -static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gengenericvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int rowoffset = 0; bool vschanged = false, pschanged = false; vector vsv, psv; vsv.put(vs, strlen(vs)+1); psv.put(ps, strlen(ps)+1); - static const int len = strlen("//:variant"), olen = strlen("override"); - for(char *vspragma = vsv.getbuf();; vschanged = true) - { + for(char *vspragma = vsv.getbuf();; vschanged = true) { vspragma = strstr(vspragma, "//:variant"); if(!vspragma) break; if(sscanf(vspragma + len, "row %d", &rowoffset) == 1) continue; memset(vspragma, ' ', len); vspragma += len; - if(!strncmp(vspragma, "override", olen)) - { + if(!strncmp(vspragma, "override", olen)) { memset(vspragma, ' ', olen); vspragma += olen; char *end = vspragma + strcspn(vspragma, "\n\r"); @@ -684,15 +597,13 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons memset(end, ' ', endlen); } } - for(char *pspragma = psv.getbuf();; pschanged = true) - { + for(char *pspragma = psv.getbuf();; pschanged = true) { pspragma = strstr(pspragma, "//:variant"); if(!pspragma) break; if(sscanf(pspragma + len, "row %d", &rowoffset) == 1) continue; memset(pspragma, ' ', len); pspragma += len; - if(!strncmp(pspragma, "override", olen)) - { + if(!strncmp(pspragma, "override", olen)) { memset(pspragma, ' ', olen); pspragma += olen; char *end = pspragma + strcspn(pspragma, "\n\r"); @@ -713,52 +624,38 @@ static void gengenericvariant(Shader &s, const char *sname, const char *vs, cons bool minimizedynlighttcusage() { return glversion < 300 && maxvaryings < 48; } -static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) -{ +static void gendynlightvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 0) { int numlights = minimizedynlighttcusage() ? 1 : MAXDYNLIGHTS; - const char *vspragma = strstr(vs, "//:dynlight"), *pspragma = strstr(ps, "//:dynlight"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:dynlight %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector vsdl, psdl; - loopi(MAXDYNLIGHTS) - { + loopi(MAXDYNLIGHTS) { vsdl.setsize(0); psdl.setsize(0); if(vsmain >= vs) vsdl.put(vs, vsmain - vs); if(psmain >= ps) psdl.put(ps, psmain - ps); - defformatstring(pos, "uniform vec4 dynlightpos[%d];\n", i+1); vsdl.put(pos, strlen(pos)); psdl.put(pos, strlen(pos)); defformatstring(color, "uniform vec3 dynlightcolor[%d];\n", i+1); psdl.put(color, strlen(color)); - - loopk(min(i+1, numlights)) - { + loopk(min(i+1, numlights)) { defformatstring(dir, "%sdynlight%ddir%s", !k ? "varying vec3 " : " ", k, k==i || k+1==numlights ? ";\n" : ","); vsdl.put(dir, strlen(dir)); psdl.put(dir, strlen(dir)); } - vsdl.put(vsmain, vspragma-vsmain); psdl.put(psmain, pspragma-psmain); - - loopk(i+1) - { + loopk(i+1) { defformatstring(tc, k%s", i+1, sname); Shader *variant = newshader(s.type, name, vsdl.getbuf(), psdl.getbuf(), &s, row); if(!variant) return; } } -static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) -{ +static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 1) { const char *vspragma = strstr(vs, "//:shadowmap"), *pspragma = strstr(ps, "//:shadowmap"); if(!vspragma || !pspragma) return; - string pslight; vspragma += strcspn(vspragma, "\n"); if(*vspragma) vspragma++; - if(sscanf(pspragma, "//:shadowmap %100s", pslight)!=1) return; - pspragma += strcspn(pspragma, "\n"); if(*pspragma) pspragma++; - const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(vsmain > vspragma) vsmain = vs; if(psmain > pspragma) psmain = ps; - vector vssm, pssm; if(vsmain >= vs) vssm.put(vs, vsmain - vs); if(psmain >= ps) pssm.put(ps, psmain - ps); - const char *vsdecl = "uniform mat4 shadowmapproject;\n" "varying vec3 shadowmaptc;\n"; vssm.put(vsdecl, strlen(vsdecl)); - const char *psdecl = "uniform sampler2D shadowmap;\n" "uniform vec4 shadowmapambient;\n" "varying vec3 shadowmaptc;\n"; pssm.put(psdecl, strlen(psdecl)); - vssm.put(vsmain, vspragma-vsmain); pssm.put(psmain, pspragma-psmain); - extern int smoothshadowmappeel; const char *tcgen = "shadowmaptc = vec3(shadowmapproject * vvertex);\n"; @@ -827,7 +711,6 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "vec2 smdiff = clamp(smvals.xz - shadowmaptc.zz*smvals.y, 0.0, 1.0);\n" "float shadowed = clamp((smdiff.x > 0.0 ? smvals.w : 0.0) - 8.0*smdiff.y, 0.0, 1.0);\n" : - "vec4 smvals = texture2D(shadowmap, shadowmaptc.xy);\n" "float smtest = shadowmaptc.z*smvals.y;\n" "float shadowed = smtest < smvals.x && smtest > smvals.z ? smvals.w : 0.0;\n"; @@ -836,32 +719,26 @@ static void genshadowmapvariant(Shader &s, const char *sname, const char *vs, co "%s.rgb -= shadowed*clamp(%s.rgb - shadowmapambient.rgb, 0.0, 1.0);\n", pslight, pslight); pssm.put(smlight, strlen(smlight)); - vssm.put(vspragma, strlen(vspragma)+1); pssm.put(pspragma, strlen(pspragma)+1); - defformatstring(name, "%s", sname); Shader *variant = newshader(s.type, name, vssm.getbuf(), pssm.getbuf(), &s, row); if(!variant) return; - if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row); } -static void genuniformdefs(vector &vsbuf, vector &psbuf, const char *vs, const char *ps, Shader *variant = NULL) -{ +static void genuniformdefs(vector &vsbuf, vector &psbuf, const char *vs, const char *ps, Shader *variant = NULL) { if(variant ? variant->defaultparams.empty() : slotparams.empty()) return; const char *vsmain = findglslmain(vs), *psmain = findglslmain(ps); if(!vsmain || !psmain) return; vsbuf.put(vs, vsmain - vs); psbuf.put(ps, psmain - ps); - if(variant) loopv(variant->defaultparams) - { + if(variant) loopv(variant->defaultparams) { defformatstring(uni, "\nuniform vec4 %s;\n", variant->defaultparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); } - else loopv(slotparams) - { + else loopv(slotparams) { defformatstring(uni, "\nuniform vec4 %s;\n", slotparams[i].name); vsbuf.put(uni, strlen(uni)); psbuf.put(uni, strlen(uni)); @@ -872,8 +749,7 @@ static void genuniformdefs(vector &vsbuf, vector &psbuf, const char VAR(defershaders, 0, 1, 1); -void defershader(int *type, const char *name, const char *contents) -{ +void defershader(int *type, const char *name, const char *contents) { Shader *exists = shaders.access(name); if(exists && !exists->invalid()) return; if(!defershaders) { execute(contents); return; } @@ -886,10 +762,8 @@ void defershader(int *type, const char *name, const char *contents) s.standard = standardshaders; } -void Shader::force() -{ +void Shader::force() { if(!deferred() || !defer) return; - char *cmd = defer; defer = NULL; bool wasstandard = standardshaders, wasforcing = forceshaders; @@ -903,24 +777,20 @@ void Shader::force() forceshaders = wasforcing; standardshaders = wasstandard; delete[] cmd; - - if(deferred()) - { + if(deferred()) { DELETEA(defer); type = SHADER_INVALID; } } -void fixshaderdetail() -{ +void fixshaderdetail() { // must null out separately because fixdetailshader can recursively set it enumerate(shaders, Shader, s, { if(!s.forced) s.detailshader = NULL; }); enumerate(shaders, Shader, s, { if(s.forced) s.fixdetailshader(); }); linkslotshaders(); } -int Shader::uniformlocversion() -{ +int Shader::uniformlocversion() { static int version = 0; if(++version >= 0) return version; version = 0; @@ -930,28 +800,23 @@ int Shader::uniformlocversion() VARFP(shaderdetail, 0, MAXSHADERDETAIL, MAXSHADERDETAIL, fixshaderdetail()); -void Shader::fixdetailshader(bool shouldforce, bool recurse) -{ +void Shader::fixdetailshader(bool shouldforce, bool recurse) { Shader *alt = this; detailshader = NULL; - do - { + do { Shader *cur = shaderdetail < MAXSHADERDETAIL ? alt->fastshader[shaderdetail] : alt; if(cur->deferred() && shouldforce) cur->force(); - if(!cur->invalid()) - { + if(!cur->invalid()) { if(cur->deferred()) break; detailshader = cur; break; } alt = alt->altshader; } while(alt && alt!=this); - if(recurse && detailshader) loopv(detailshader->variants) detailshader->variants[i]->fixdetailshader(shouldforce, false); } -Shader *useshaderbyname(const char *name) -{ +Shader *useshaderbyname(const char *name) { Shader *s = shaders.access(name); if(!s) return NULL; if(!s->detailshader) s->fixdetailshader(); @@ -959,17 +824,14 @@ Shader *useshaderbyname(const char *name) return s; } -void shader(int *type, char *name, char *vs, char *ps) -{ +void shader(int *type, char *name, char *vs, char *ps) { if(lookupshaderbyname(name)) return; - defformatstring(info, "shader %s", name); renderprogress(loadprogress, info); - vector vsbuf, psbuf, vsbak, psbak; #define GENSHADER(cond, body) \ - if(cond) \ - { \ + if(cond) { \ + \ if(vsbuf.length()) { vsbak.setsize(0); vsbak.put(vs, strlen(vs)+1); vs = vsbak.getbuf(); vsbuf.setsize(0); } \ if(psbuf.length()) { psbak.setsize(0); psbak.put(ps, strlen(ps)+1); ps = psbak.getbuf(); psbuf.setsize(0); } \ body; \ @@ -978,78 +840,63 @@ void shader(int *type, char *name, char *vs, char *ps) } GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps)); Shader *s = newshader(*type, name, vs, ps); - if(s) - { + if(s) { if(strstr(vs, "//:shadowmap")) genshadowmapvariant(*s, s->name, vs, ps); if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, s->name, vs, ps); } slotparams.shrink(0); } -void variantshader(int *type, char *name, int *row, char *vs, char *ps) -{ - if(*row < 0) - { +void variantshader(int *type, char *name, int *row, char *vs, char *ps) { + if(*row < 0) { shader(type, name, vs, ps); return; } else if(*row >= MAXVARIANTROWS) return; - Shader *s = lookupshaderbyname(name); if(!s) return; - defformatstring(varname, "%s", s->numvariants(*row), *row, name); //defformatstring(info, "shader %s", varname); //renderprogress(loadprogress, info); vector vsbuf, psbuf, vsbak, psbak; GENSHADER(s->defaultparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps, s)); Shader *v = newshader(*type, varname, vs, ps, s, *row); - if(v) - { + if(v) { if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, varname, vs, ps, *row); if(strstr(ps, "//:variant") || strstr(vs, "//:variant")) gengenericvariant(*s, varname, vs, ps, *row); } } -void setshader(char *name) -{ +void setshader(char *name) { slotparams.shrink(0); Shader *s = shaders.access(name); - if(!s) - { + if(!s) { conoutf(CON_ERROR, "no such shader: %s", name); } else slotshader = s; } -void resetslotshader() -{ +void resetslotshader() { slotshader = NULL; slotparams.shrink(0); } -void setslotshader(Slot &s) -{ +void setslotshader(Slot &s) { s.shader = slotshader; - if(!s.shader) - { + if(!s.shader) { s.shader = stdworldshader; return; } loopv(slotparams) s.params.add(slotparams[i]); } -static void linkslotshaderparams(vector ¶ms, Shader *sh, bool load) -{ - if(sh) loopv(params) - { +static void linkslotshaderparams(vector ¶ms, Shader *sh, bool load) { + if(sh) loopv(params) { int loc = -1; SlotShaderParam ¶m = params[i]; - loopv(sh->defaultparams) - { + loopv(sh->defaultparams) { SlotShaderParamState &dparam = sh->defaultparams[i]; - if(dparam.name==param.name) - { + if(dparam.name==param.name) { if(memcmp(param.val, dparam.val, sizeof(param.val))) loc = i; break; } @@ -1059,35 +906,27 @@ static void linkslotshaderparams(vector ¶ms, Shader *sh, bo else if(load) loopv(params) params[i].loc = -1; } -void linkslotshader(Slot &s, bool load) -{ +void linkslotshader(Slot &s, bool load) { if(!s.shader) return; - if(load && !s.shader->detailshader) s.shader->fixdetailshader(); - linkslotshaderparams(s.params, s.shader->detailshader, load); } -void linkvslotshader(VSlot &s, bool load) -{ +void linkvslotshader(VSlot &s, bool load) { if(!s.slot->shader) return; - Shader *sh = s.slot->shader->detailshader; linkslotshaderparams(s.params, sh, load); - if(!sh) return; } -void altshader(char *origname, char *altname) -{ +void altshader(char *origname, char *altname) { Shader *orig = shaders.access(origname), *alt = shaders.access(altname); if(!orig || !alt) return; orig->altshader = alt; orig->fixdetailshader(false); } -void fastshader(char *nice, char *fast, int *detail) -{ +void fastshader(char *nice, char *fast, int *detail) { Shader *ns = shaders.access(nice), *fs = shaders.access(fast); if(!ns || !fs) return; loopi(min(*detail+1, MAXSHADERDETAIL)) ns->fastshader[i] = fs; @@ -1106,21 +945,17 @@ ICOMMAND(isshaderdefined, "s", (char *name), intret(lookupshaderbyname(name) ? 1 static hashset shaderparamnames(256); -const char *getshaderparamname(const char *name, bool insert) -{ +const char *getshaderparamname(const char *name, bool insert) { const char *exists = shaderparamnames.find(name, NULL); if(exists || !insert) return exists; return shaderparamnames.add(newstring(name)); } -void addslotparam(const char *name, float x, float y, float z, float w) -{ +void addslotparam(const char *name, float x, float y, float z, float w) { if(name) name = getshaderparamname(name); - loopv(slotparams) - { + loopv(slotparams) { SlotShaderParam ¶m = slotparams[i]; - if(param.name==name) - { + if(param.name==name) { param.val[0] = x; param.val[1] = y; param.val[2] = z; @@ -1136,8 +971,7 @@ ICOMMAND(setuniformparam, "sffff", (char *name, float *x, float *y, float *z, fl ICOMMAND(setshaderparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); ICOMMAND(defuniformparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w)); -void cleanupshaders() -{ +void cleanupshaders() { loadedshaders = false; nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = stdworldshader = NULL; enumerate(shaders, Shader, s, s.cleanup()); @@ -1145,21 +979,17 @@ void cleanupshaders() glUseProgram_(0); } -void reloadshaders() -{ +void reloadshaders() { identflags &= ~IDF_PERSIST; loadshaders(); identflags |= IDF_PERSIST; linkslotshaders(); - enumerate(shaders, Shader, s, - { - if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) - { + enumerate(shaders, Shader, s, { + if(!s.standard && !(s.type&(SHADER_DEFERRED|SHADER_INVALID)) && !s.variantshader) { defformatstring(info, "shader %s", s.name); renderprogress(0.0, info); if(!s.compile()) s.cleanup(true); - loopv(s.variants) - { + loopv(s.variants) { Shader *v = s.variants[i]; if((v->reusevs && v->reusevs->invalid()) || (v->reuseps && v->reuseps->invalid()) || @@ -1171,8 +1001,7 @@ void reloadshaders() }); } -void setupblurkernel(int radius, float sigma, float *weights, float *offsets) -{ +void setupblurkernel(int radius, float sigma, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; sigma *= 2*radius; float total = 1.0f/sigma; @@ -1180,8 +1009,7 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) offsets[0] = 0; // rely on bilinear filtering to sample 2 pixels at once // transforms a*X + b*Y into (u+v)*[X*u/(u+v) + Y*(1 - u/(u+v))] - loopi(radius) - { + loopi(radius) { float weight1 = exp(-((2*i)*(2*i)) / (2*sigma*sigma)) / sigma, weight2 = exp(-((2*i+1)*(2*i+1)) / (2*sigma*sigma)) / sigma, scale = weight1 + weight2, @@ -1194,13 +1022,11 @@ void setupblurkernel(int radius, float sigma, float *weights, float *offsets) for(int i = radius+1; i <= MAXBLURRADIUS; i++) weights[i] = offsets[i] = 0; } -void setblurshader(int pass, int size, int radius, float *weights, float *offsets) -{ +void setblurshader(int pass, int size, int radius, float *weights, float *offsets) { if(radius<1 || radius>MAXBLURRADIUS) return; static Shader *blurshader[7][2] = { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }; Shader *&s = blurshader[radius-1][pass]; - if(!s) - { + if(!s) { defformatstring(name, "blur%c%d", 'x'+pass, radius); s = lookupshaderbyname(name); } -- cgit v1.2.3