summaryrefslogtreecommitdiff
path: root/src/engine/shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/shader.cpp')
-rw-r--r--src/engine/shader.cpp448
1 files changed, 137 insertions, 311 deletions
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<<a.loc;
}
loopi(gle::MAXATTRIBS) if(!(attribs&(1<<i))) glBindAttribLocation_(s.program, i, gle::attribnames[i]);
- if(glversion >= 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 &param = 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, "<init>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<char> 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<char> 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<numlights ?
"dynlight%ddir = vvertex.xyz*dynlightpos[%d].w + dynlightpos[%d].xyz;\n" :
@@ -766,58 +663,45 @@ static void gendynlightvariant(Shader &s, const char *sname, const char *vs, con
k, k, k);
if(k < numlights) vsdl.put(tc, strlen(tc));
else psdl.put(tc, strlen(tc));
-
defformatstring(dl,
"%s.rgb += dynlightcolor[%d] * (1.0 - clamp(dot(dynlight%ddir, dynlight%ddir), 0.0, 1.0));\n",
pslight, k, k, k);
psdl.put(dl, strlen(dl));
}
-
vsdl.put(vspragma, strlen(vspragma)+1);
psdl.put(pspragma, strlen(pspragma)+1);
-
defformatstring(name, "<dynlight %d>%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<char> 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, "<shadowmap>%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<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps, Shader *variant = NULL)
-{
+static void genuniformdefs(vector<char> &vsbuf, vector<char> &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<char> &vsbuf, vector<char> &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<char> 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, "<variant:%d,%d>%s", s->numvariants(*row), *row, name);
//defformatstring(info, "shader %s", varname);
//renderprogress(loadprogress, info);
vector<char> 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<SlotShaderParam> &params, Shader *sh, bool load)
-{
- if(sh) loopv(params)
- {
+static void linkslotshaderparams(vector<SlotShaderParam> &params, Shader *sh, bool load) {
+ if(sh) loopv(params) {
int loc = -1;
SlotShaderParam &param = 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<SlotShaderParam> &params, 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<const char *> 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 &param = 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);
}