summaryrefslogtreecommitdiff
path: root/src/engine/shader.cpp
diff options
context:
space:
mode:
authorxolatile2025-08-04 22:53:42 +0200
committerxolatile2025-08-04 22:53:42 +0200
commitd309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch)
tree999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/engine/shader.cpp
parent29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff)
downloadxolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz
xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst
Bunch of small changes...
Diffstat (limited to 'src/engine/shader.cpp')
-rw-r--r--src/engine/shader.cpp2373
1 files changed, 1184 insertions, 1189 deletions
diff --git a/src/engine/shader.cpp b/src/engine/shader.cpp
index da17d4f..f7a740e 100644
--- a/src/engine/shader.cpp
+++ b/src/engine/shader.cpp
@@ -17,1206 +17,1201 @@ VAR(reservevpparams, 1, 16, 0);
VAR(maxvsuniforms, 1, 0, 0);
VAR(maxfsuniforms, 1, 0, 0);
VAR(maxvaryings, 1, 0, 0);
-VAR(dbgshader, 0, 0, 2);
void loadshaders()
{
- standardshaders = true;
- execfile("data/glsl.cfg");
- standardshaders = false;
+ 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");
+ 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;
+ dummyslot.shader = stdworldshader;
- textureshader = lookupshaderbyname("texture");
- notextureshader = lookupshaderbyname("notexture");
- nocolorshader = lookupshaderbyname("nocolor");
- foggedshader = lookupshaderbyname("fogged");
- foggednotextureshader = lookupshaderbyname("foggednotexture");
-
- nullshader->set();
+ textureshader = lookupshaderbyname("texture");
+ notextureshader = lookupshaderbyname("notexture");
+ nocolorshader = lookupshaderbyname("nocolor");
+ foggedshader = lookupshaderbyname("fogged");
+ foggednotextureshader = lookupshaderbyname("foggednotexture");
- loadedshaders = true;
+ nullshader->set();
+
+ loadedshaders = true;
}
-Shader *lookupshaderbyname(const char *name)
-{
- Shader *s = shaders.access(name);
- return s && s->loaded() ? s : NULL;
+Shader *lookupshaderbyname(const char *name)
+{
+ Shader *s = shaders.access(name);
+ return s && s->loaded() ? s : NULL;
}
Shader *generateshader(const char *name, const char *fmt, ...)
{
- if(!loadedshaders) return NULL;
- Shader *s = name ? lookupshaderbyname(name) : NULL;
- if(!s)
- {
- defvformatstring(cmd, fmt, fmt);
- bool wasstandard = standardshaders;
- standardshaders = true;
- execute(cmd);
- standardshaders = wasstandard;
- s = name ? lookupshaderbyname(name) : NULL;
- if(!s) s = nullshader;
- }
- return s;
+ if(!loadedshaders) return NULL;
+ Shader *s = name ? lookupshaderbyname(name) : NULL;
+ if(!s)
+ {
+ defvformatstring(cmd, fmt, fmt);
+ bool wasstandard = standardshaders;
+ standardshaders = true;
+ execute(cmd);
+ standardshaders = wasstandard;
+ s = name ? lookupshaderbyname(name) : NULL;
+ if(!s) s = nullshader;
+ }
+ return s;
}
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)
- {
- conoutf(CON_ERROR, "GLSL ERROR (%s:%s)", type == GL_VERTEX_SHADER ? "VS" : (type == GL_FRAGMENT_SHADER ? "FS" : "PROG"), name);
- FILE *l = getlogfile();
- 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)
- {
- const char *part = parts[i];
- int startline = line;
- 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);
- fwrite(part, 1, next ? next - part + 1 : strlen(part), l);
- if(!next) { fputc('\n', l); break; }
- part = next + 1;
- }
- }
- done:
- delete[] log;
- }
- }
+ GLint length = 0;
+ if(type) glGetShaderiv_(obj, GL_INFO_LOG_LENGTH, &length);
+ else glGetProgramiv_(obj, GL_INFO_LOG_LENGTH, &length);
+ 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)
+ {
+ 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)
+ {
+ const char *part = parts[i];
+ int startline = line;
+ 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);
+ fwrite(part, 1, next ? next - part + 1 : strlen(part), l);
+ if(!next) { fputc('\n', l); break; }
+ part = next + 1;
+ }
+ }
+ done:
+ delete[] log;
+ }
+ }
}
-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" }
- };
- loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version)
- {
- parts[numparts++] = glslversions[i].header;
- break;
- }
- if(glslversion >= 130)
- {
- if(type == GL_VERTEX_SHADER) parts[numparts++] =
- "#define attribute in\n"
- "#define varying out\n";
- 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++] =
- "out vec4 cube2_FragColor;\n"
- "#define gl_FragColor cube2_FragColor\n";
- }
- parts[numparts++] =
- "#define texture2D(sampler, coords) texture(sampler, coords)\n"
- "#define texture2DProj(sampler, coords) textureProj(sampler, coords)\n"
- "#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(msg) showglslinfo(type, obj, name, parts, numparts);
- glDeleteShader_(obj);
- obj = 0;
- }
- else if(dbgshader > 1 && msg) showglslinfo(type, obj, name, parts, numparts);
-}
-
-VAR(dbgubo, 0, 0, 1);
+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" }
+ };
+ loopi(sizeof(glslversions)/sizeof(glslversions[0])) if(glslversion >= glslversions[i].version)
+ {
+ parts[numparts++] = glslversions[i].header;
+ break;
+ }
+ if(glslversion >= 130)
+ {
+ if(type == GL_VERTEX_SHADER) parts[numparts++] =
+ "#define attribute in\n"
+ "#define varying out\n";
+ 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++] =
+ "out vec4 cube2_FragColor;\n"
+ "#define gl_FragColor cube2_FragColor\n";
+ }
+ parts[numparts++] =
+ "#define texture2D(sampler, coords) texture(sampler, coords)\n"
+ "#define texture2DProj(sampler, coords) textureProj(sampler, coords)\n"
+ "#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(msg) showglslinfo(type, obj, name, parts, numparts);
+ glDeleteShader_(obj);
+ obj = 0;
+ }
+}
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)
- {
- 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)
- {
- glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_ARRAY_STRIDE, &strideval);
- if(strideval > u.stride) return;
- }
- u.offset = offsetval;
- u.size = sizeval;
- glUniformBlockBinding_(s.program, bidx, u.binding);
- if(dbgubo) conoutf(CON_DEBUG, "UBO: %s:%s:%d, offset: %d, size: %d, stride: %d", u.name, u.blockname, u.binding, offsetval, sizeval, strideval);
- }
+ 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)
+ {
+ 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)
+ {
+ glGetActiveUniformsiv_(s.program, 1, &uidx, GL_UNIFORM_ARRAY_STRIDE, &strideval);
+ if(strideval > u.stride) return;
+ }
+ u.offset = offsetval;
+ u.size = sizeval;
+ glUniformBlockBinding_(s.program, bidx, u.binding);
+ }
}
static void linkglslprogram(Shader &s, bool msg = true)
{
- s.program = s.vsobj && s.psobj ? glCreateProgram_() : 0;
- GLint success = 0;
- if(s.program)
- {
- glAttachShader_(s.program, s.vsobj);
- glAttachShader_(s.program, s.psobj);
- uint attribs = 0;
- 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)
- {
- glBindFragDataLocation_(s.program, 0, "cube2_FragColor");
- }
- glLinkProgram_(s.program);
- glGetProgramiv_(s.program, GL_LINK_STATUS, &success);
- }
- if(success)
- {
- glUseProgram_(s.program);
- 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)
- {
- 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)
- {
- if(msg) showglslinfo(GL_FALSE, s.program, s.name);
- glDeleteProgram_(s.program);
- s.program = 0;
- }
+ s.program = s.vsobj && s.psobj ? glCreateProgram_() : 0;
+ GLint success = 0;
+ if(s.program)
+ {
+ glAttachShader_(s.program, s.vsobj);
+ glAttachShader_(s.program, s.psobj);
+ uint attribs = 0;
+ 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)
+ {
+ glBindFragDataLocation_(s.program, 0, "cube2_FragColor");
+ }
+ glLinkProgram_(s.program);
+ glGetProgramiv_(s.program, GL_LINK_STATUS, &success);
+ }
+ if(success)
+ {
+ glUseProgram_(s.program);
+ 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)
+ {
+ 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)
+ {
+ if(msg) showglslinfo(GL_FALSE, s.program, s.name);
+ glDeleteProgram_(s.program);
+ s.program = 0;
+ }
}
int getlocalparam(const char *name)
{
- return localparams.access(name, int(localparams.numelems));
+ return localparams.access(name, int(localparams.numelems));
}
static int addlocalparam(Shader &s, const char *name, int loc, int size, GLenum format)
{
- int idx = getlocalparam(name);
- 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;
- l.size = size;
- l.format = format;
- return idx;
+ int idx = getlocalparam(name);
+ 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;
+ l.size = size;
+ l.format = format;
+ return idx;
}
GlobalShaderParamState *getglobalparam(const char *name)
{
- GlobalShaderParamState *param = globalparams.access(name);
- if(!param)
- {
- param = &globalparams[name];
- param->name = name;
- memset(param->buf, -1, sizeof(param->buf));
- param->version = -1;
- }
- return param;
+ GlobalShaderParamState *param = globalparams.access(name);
+ if(!param)
+ {
+ param = &globalparams[name];
+ param->name = name;
+ memset(param->buf, -1, sizeof(param->buf));
+ param->version = -1;
+ }
+ return param;
}
static GlobalShaderParamUse *addglobalparam(Shader &s, GlobalShaderParamState *param, int loc, int size, GLenum format)
{
- GlobalShaderParamUse &g = s.globalparams.add();
- g.param = param;
- g.version = -2;
- g.loc = loc;
- g.size = size;
- g.format = format;
- return &g;
+ GlobalShaderParamUse &g = s.globalparams.add();
+ g.param = param;
+ g.version = -2;
+ g.loc = loc;
+ g.size = size;
+ g.format = format;
+ return &g;
}
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:
- case GL_FLOAT_VEC4:
- case GL_INT:
- case GL_INT_VEC2:
- case GL_INT_VEC3:
- case GL_INT_VEC4:
- case GL_BOOL:
- case GL_BOOL_VEC2:
- case GL_BOOL_VEC3:
- case GL_BOOL_VEC4:
- case GL_FLOAT_MAT2:
- case GL_FLOAT_MAT3:
- case GL_FLOAT_MAT4:
- break;
- default:
- 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)
- {
- 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);
+ switch(format)
+ {
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ break;
+ default:
+ 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)
+ {
+ 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)
{
- GLint numactive = 0;
- glGetProgramiv_(s.program, GL_ACTIVE_UNIFORMS, &numactive);
- string name;
- loopi(numactive)
- {
- GLsizei namelen = 0;
- GLint size = 0;
- GLenum format = GL_FLOAT_VEC4;
- name[0] = '\0';
- glGetActiveUniform_(s.program, i, sizeof(name)-1, &namelen, &size, &format, name);
- if(namelen <= 0 || size <= 0) continue;
- name[clamp(int(namelen), 0, (int)sizeof(name)-2)] = '\0';
- char *brak = strchr(name, '[');
- if(brak) *brak = '\0';
- setglsluniformformat(s, name, format, size);
- }
+ GLint numactive = 0;
+ glGetProgramiv_(s.program, GL_ACTIVE_UNIFORMS, &numactive);
+ string name;
+ loopi(numactive)
+ {
+ GLsizei namelen = 0;
+ GLint size = 0;
+ GLenum format = GL_FLOAT_VEC4;
+ name[0] = '\0';
+ glGetActiveUniform_(s.program, i, sizeof(name)-1, &namelen, &size, &format, name);
+ if(namelen <= 0 || size <= 0) continue;
+ name[clamp(int(namelen), 0, (int)sizeof(name)-2)] = '\0';
+ char *brak = strchr(name, '[');
+ if(brak) *brak = '\0';
+ setglsluniformformat(s, name, format, size);
+ }
}
void Shader::allocparams(Slot *slot)
{
- if(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)
- {
- UNIFORMTEX("lmcolor", 1);
- UNIFORMTEX("lmdir", 2);
- tmu++;
- }
- else UNIFORMTEX("lightmap", 1);
- if(type & SHADER_ENVMAP) UNIFORMTEX("envmap", tmu++);
- UNIFORMTEX("shadowmap", 7);
- int stex = 0;
- loopv(slot->sts)
- {
- Slot::Tex &t = slot->sts[i];
- switch(t.type)
- {
- case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break;
- case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break;
- case TEX_GLOW: UNIFORMTEX("glowmap", 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:
- {
- defformatstring(sname, "stex%d", stex++);
- UNIFORMTEX(sname, tmu++);
- break;
- }
- }
- }
- }
- allocglslactiveuniforms(*this);
+ { \
+ loc = glGetUniformLocation_(program, name); \
+ int val = tmu; \
+ if(loc != -1) glUniform1i_(loc, val); \
+ }
+ int loc, tmu = 2;
+ if(type & SHADER_NORMALSLMS)
+ {
+ UNIFORMTEX("lmcolor", 1);
+ UNIFORMTEX("lmdir", 2);
+ tmu++;
+ }
+ else UNIFORMTEX("lightmap", 1);
+ if(type & SHADER_ENVMAP) UNIFORMTEX("envmap", tmu++);
+ UNIFORMTEX("shadowmap", 7);
+ int stex = 0;
+ loopv(slot->sts)
+ {
+ Slot::Tex &t = slot->sts[i];
+ switch(t.type)
+ {
+ case TEX_DIFFUSE: UNIFORMTEX("diffusemap", 0); break;
+ case TEX_NORMAL: UNIFORMTEX("normalmap", tmu++); break;
+ case TEX_GLOW: UNIFORMTEX("glowmap", 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:
+ {
+ defformatstring(sname, "stex%d", stex++);
+ UNIFORMTEX(sname, tmu++);
+ break;
+ }
+ }
+ }
+ }
+ allocglslactiveuniforms(*this);
}
int GlobalShaderParamState::nextversion = 0;
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)
- {
- GlobalShaderParamUse &u = s.globalparams[i];
- if(u.version >= 0) u.version = u.param->version;
- }
- });
+ 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)
+ {
+ GlobalShaderParamUse &u = s.globalparams[i];
+ if(u.version >= 0) u.version = u.param->version;
+ }
+ });
}
static float *findslotparam(Slot &s, const char *name, float *noval = NULL)
{
- loopv(s.params)
- {
- SlotShaderParam &param = s.params[i];
- if(name == param.name) return param.val;
- }
- loopv(s.shader->defaultparams)
- {
- SlotShaderParamState &param = s.shader->defaultparams[i];
- if(name == param.name) return param.val;
- }
- return noval;
+ loopv(s.params)
+ {
+ SlotShaderParam &param = s.params[i];
+ if(name == param.name) return param.val;
+ }
+ loopv(s.shader->defaultparams)
+ {
+ SlotShaderParamState &param = s.shader->defaultparams[i];
+ if(name == param.name) return param.val;
+ }
+ return noval;
}
static float *findslotparam(VSlot &s, const char *name, float *noval = NULL)
{
- loopv(s.params)
- {
- SlotShaderParam &param = s.params[i];
- if(name == param.name) return param.val;
- }
- return findslotparam(*s.slot, name, noval);
+ loopv(s.params)
+ {
+ SlotShaderParam &param = s.params[i];
+ if(name == param.name) return param.val;
+ }
+ return findslotparam(*s.slot, name, noval);
}
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:
- case GL_FLOAT_VEC2: glUniform2fv_(l.loc, 1, val); break;
- case GL_BOOL_VEC3:
- case GL_FLOAT_VEC3: glUniform3fv_(l.loc, 1, val); break;
- case GL_BOOL_VEC4:
- case GL_FLOAT_VEC4: glUniform4fv_(l.loc, 1, val); break;
- case GL_INT: glUniform1i_(l.loc, int(val[0])); break;
- case GL_INT_VEC2: glUniform2i_(l.loc, int(val[0]), int(val[1])); break;
- case GL_INT_VEC3: glUniform3i_(l.loc, int(val[0]), int(val[1]), int(val[2])); break;
- case GL_INT_VEC4: glUniform4i_(l.loc, int(val[0]), int(val[1]), int(val[2]), int(val[3])); break;
- }
+ switch(l.format)
+ {
+ case GL_BOOL:
+ case GL_FLOAT: glUniform1fv_(l.loc, 1, val); break;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2: glUniform2fv_(l.loc, 1, val); break;
+ case GL_BOOL_VEC3:
+ case GL_FLOAT_VEC3: glUniform3fv_(l.loc, 1, val); break;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4: glUniform4fv_(l.loc, 1, val); break;
+ case GL_INT: glUniform1i_(l.loc, int(val[0])); break;
+ case GL_INT_VEC2: glUniform2i_(l.loc, int(val[0]), int(val[1])); break;
+ case GL_INT_VEC3: glUniform3i_(l.loc, int(val[0]), int(val[1]), int(val[2])); break;
+ case GL_INT_VEC4: glUniform4i_(l.loc, int(val[0]), int(val[1]), int(val[2]), int(val[3])); break;
+ }
}
#define SETSLOTPARAM(l, mask, i, val) do { \
- if(!(mask&(1<<i))) { \
- mask |= 1<<i; \
- setslotparam(l, val); \
- } \
+ if(!(mask&(1<<i))) { \
+ mask |= 1<<i; \
+ setslotparam(l, val); \
+ } \
} while(0)
#define SETSLOTPARAMS(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); \
- }
+ 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) \
- { \
- SlotShaderParamState &l = defaultparams[i]; \
- SETSLOTPARAM(l, unimask, i, l.val); \
- }
+ loopv(defaultparams) \
+ { \
+ SlotShaderParamState &l = defaultparams[i]; \
+ SETSLOTPARAM(l, unimask, i, l.val); \
+ }
void Shader::setslotparams(Slot &slot)
{
- uint unimask = 0;
- SETSLOTPARAMS(slot.params)
- SETDEFAULTPARAMS
+ uint unimask = 0;
+ SETSLOTPARAMS(slot.params)
+ SETDEFAULTPARAMS
}
void Shader::setslotparams(Slot &slot, VSlot &vslot)
{
- uint unimask = 0;
- if(vslot.slot == &slot)
- {
- SETSLOTPARAMS(vslot.params)
- SETSLOTPARAMS(slot.params)
- SETDEFAULTPARAMS
- }
- else
- {
- SETSLOTPARAMS(slot.params)
- SETDEFAULTPARAMS
- }
+ uint unimask = 0;
+ if(vslot.slot == &slot)
+ {
+ SETSLOTPARAMS(vslot.params)
+ SETSLOTPARAMS(slot.params)
+ SETDEFAULTPARAMS
+ }
+ else
+ {
+ SETSLOTPARAMS(slot.params)
+ SETDEFAULTPARAMS
+ }
}
void Shader::bindprograms()
{
- if(this == lastshader || type&(SHADER_DEFERRED|SHADER_INVALID)) return;
- glUseProgram_(program);
- lastshader = this;
+ if(this == lastshader || type&(SHADER_DEFERRED|SHADER_INVALID)) return;
+ glUseProgram_(program);
+ lastshader = this;
}
bool Shader::compile()
{
- if(!vsstr) vsobj = !reusevs || reusevs->invalid() ? 0 : reusevs->vsobj;
- else compileglslshader(GL_VERTEX_SHADER, vsobj, vsstr, name, dbgshader || !variantshader);
- if(!psstr) psobj = !reuseps || reuseps->invalid() ? 0 : reuseps->psobj;
- else compileglslshader(GL_FRAGMENT_SHADER, psobj, psstr, name, dbgshader || !variantshader);
- linkglslprogram(*this, !variantshader);
- return program!=0;
+ 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;
+ else compileglslshader(GL_FRAGMENT_SHADER, psobj, psstr, name, !variantshader);
+ linkglslprogram(*this, !variantshader);
+ return program!=0;
}
void Shader::cleanup(bool invalid)
{
- detailshader = NULL;
- used = false;
- if(vsobj) { if(!reusevs) glDeleteShader_(vsobj); vsobj = 0; }
- if(psobj) { if(!reuseps) glDeleteShader_(psobj); psobj = 0; }
- if(program) { glDeleteProgram_(program); program = 0; }
- localparams.setsize(0);
- localparamremap.setsize(0);
- globalparams.setsize(0);
- if(standard || invalid)
- {
- type = SHADER_INVALID;
- DELETEA(vsstr);
- DELETEA(psstr);
- DELETEA(defer);
- variants.setsize(0);
- DELETEA(variantrows);
- defaultparams.setsize(0);
- attriblocs.setsize(0);
- uniformlocs.setsize(0);
- altshader = NULL;
- loopi(MAXSHADERDETAIL) fastshader[i] = this;
- reusevs = reuseps = NULL;
- }
- else loopv(defaultparams) defaultparams[i].loc = -1;
- owner = NULL;
+ detailshader = NULL;
+ used = false;
+ if(vsobj) { if(!reusevs) glDeleteShader_(vsobj); vsobj = 0; }
+ if(psobj) { if(!reuseps) glDeleteShader_(psobj); psobj = 0; }
+ if(program) { glDeleteProgram_(program); program = 0; }
+ localparams.setsize(0);
+ localparamremap.setsize(0);
+ globalparams.setsize(0);
+ if(standard || invalid)
+ {
+ type = SHADER_INVALID;
+ DELETEA(vsstr);
+ DELETEA(psstr);
+ DELETEA(defer);
+ variants.setsize(0);
+ DELETEA(variantrows);
+ defaultparams.setsize(0);
+ attriblocs.setsize(0);
+ uniformlocs.setsize(0);
+ altshader = NULL;
+ loopi(MAXSHADERDETAIL) fastshader[i] = this;
+ reusevs = reuseps = NULL;
+ }
+ else loopv(defaultparams) defaultparams[i].loc = -1;
+ owner = NULL;
}
bool Shader::isnull(const Shader *s) { return !s; }
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")))
- {
- if(sscanf(vs, "//:attrib %100s %d", name, &loc) == 2)
- s.attriblocs.add(AttribLoc(getshaderparamname(name), loc));
- vs += len;
- }
+ static int len = strlen("//:attrib");
+ string name;
+ int loc;
+ if(reusevs) s.attriblocs = reusevs->attriblocs;
+ 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 int len = strlen("//:uniform");
- string name, blockname;
- int binding, stride;
- if(reusevs) s.uniformlocs = reusevs->uniformlocs;
- 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)));
- vs += len;
- }
+ static int len = strlen("//:uniform");
+ string name, blockname;
+ int binding, stride;
+ if(reusevs) s.uniformlocs = reusevs->uniformlocs;
+ 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)));
+ vs += len;
+ }
}
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];
- s.name = rname;
- s.vsstr = newstring(vs);
- s.psstr = newstring(ps);
- DELETEA(s.defer);
- s.type = type;
- s.variantshader = variant;
- s.standard = standardshaders;
- if(forceshaders) s.forced = true;
- s.reusevs = s.reuseps = NULL;
- if(variant)
- {
- int row = 0, col = 0;
- 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)
- {
- DELETEA(s.psstr);
- s.reuseps = !ps[0] ? variant : variant->getvariant(col, row);
- }
- }
- if(variant) loopv(variant->defaultparams) s.defaultparams.add(variant->defaultparams[i]);
- else loopv(slotparams) s.defaultparams.add(slotparams[i]);
- s.attriblocs.setsize(0);
- s.uniformlocs.setsize(0);
- genattriblocs(s, vs, ps, s.reusevs, s.reuseps);
- genuniformlocs(s, vs, ps, s.reusevs, s.reuseps);
- if(!s.compile())
- {
- s.cleanup(true);
- if(variant) shaders.remove(rname);
- return NULL;
- }
- if(variant) variant->addvariant(row, &s);
- s.fixdetailshader();
- return &s;
+ if(Shader::lastshader)
+ {
+ glUseProgram_(0);
+ Shader::lastshader = NULL;
+ }
+
+ Shader *exists = shaders.access(name);
+ char *rname = exists ? exists->name : newstring(name);
+ Shader &s = shaders[rname];
+ s.name = rname;
+ s.vsstr = newstring(vs);
+ s.psstr = newstring(ps);
+ DELETEA(s.defer);
+ s.type = type;
+ s.variantshader = variant;
+ s.standard = standardshaders;
+ if(forceshaders) s.forced = true;
+ s.reusevs = s.reuseps = NULL;
+ if(variant)
+ {
+ int row = 0, col = 0;
+ 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)
+ {
+ DELETEA(s.psstr);
+ s.reuseps = !ps[0] ? variant : variant->getvariant(col, row);
+ }
+ }
+ if(variant) loopv(variant->defaultparams) s.defaultparams.add(variant->defaultparams[i]);
+ else loopv(slotparams) s.defaultparams.add(slotparams[i]);
+ s.attriblocs.setsize(0);
+ s.uniformlocs.setsize(0);
+ genattriblocs(s, vs, ps, s.reusevs, s.reuseps);
+ genuniformlocs(s, vs, ps, s.reusevs, s.reuseps);
+ if(!s.compile())
+ {
+ s.cleanup(true);
+ if(variant) shaders.remove(rname);
+ return NULL;
+ }
+ if(variant) variant->addvariant(row, &s);
+ s.fixdetailshader();
+ return &s;
}
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)
- {
- glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &val);
- maxvaryings = val;
- }
-
- standardshaders = true;
- nullshader = newshader(0, "<init>null",
- "attribute vec4 vvertex;\n"
- "void main(void) {\n"
- " gl_Position = vvertex;\n"
- "}\n",
- "void main(void) {\n"
- " gl_FragColor = vec4(1.0, 0.0, 1.0, 0.0);\n"
- "}\n");
- hudshader = newshader(0, "<init>hud",
- "attribute vec4 vvertex, vcolor;\n"
- "attribute vec2 vtexcoord0;\n"
- "uniform mat4 hudmatrix;\n"
- "varying vec2 texcoord0;\n"
- "varying vec4 color;\n"
- "void main(void) {\n"
- " gl_Position = hudmatrix * vvertex;\n"
- " texcoord0 = vtexcoord0;\n"
- " color = vcolor;\n"
- "}\n",
- "varying vec2 texcoord0;\n"
- "varying vec4 color;\n"
- "uniform sampler2D tex0;\n"
- "void main(void) {\n"
- " gl_FragColor = color * texture2D(tex0, texcoord0);\n"
- "}\n");
- hudnotextureshader = newshader(0, "<init>hudnotexture",
- "attribute vec4 vvertex, vcolor;\n"
- "uniform mat4 hudmatrix;\n"
- "varying vec4 color;\n"
- "void main(void) {\n"
- " gl_Position = hudmatrix * vvertex;\n"
- " color = vcolor;\n"
- "}\n",
- "varying vec4 color;\n"
- "void main(void) {\n"
- " gl_FragColor = color;\n"
- "}\n");
- standardshaders = false;
-
- if(!nullshader || !hudshader || !hudnotextureshader) fatal("failed to setup shaders");
-
- dummyslot.shader = nullshader;
+ 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)
+ {
+ glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &val);
+ maxvaryings = val;
+ }
+
+ standardshaders = true;
+ nullshader = newshader(0, "<init>null",
+ "attribute vec4 vvertex;\n"
+ "void main(void) {\n"
+ " gl_Position = vvertex;\n"
+ "}\n",
+ "void main(void) {\n"
+ " gl_FragColor = vec4(1.0, 0.0, 1.0, 0.0);\n"
+ "}\n");
+ hudshader = newshader(0, "<init>hud",
+ "attribute vec4 vvertex, vcolor;\n"
+ "attribute vec2 vtexcoord0;\n"
+ "uniform mat4 hudmatrix;\n"
+ "varying vec2 texcoord0;\n"
+ "varying vec4 color;\n"
+ "void main(void) {\n"
+ " gl_Position = hudmatrix * vvertex;\n"
+ " texcoord0 = vtexcoord0;\n"
+ " color = vcolor;\n"
+ "}\n",
+ "varying vec2 texcoord0;\n"
+ "varying vec4 color;\n"
+ "uniform sampler2D tex0;\n"
+ "void main(void) {\n"
+ " gl_FragColor = color * texture2D(tex0, texcoord0);\n"
+ "}\n");
+ hudnotextureshader = newshader(0, "<init>hudnotexture",
+ "attribute vec4 vvertex, vcolor;\n"
+ "uniform mat4 hudmatrix;\n"
+ "varying vec4 color;\n"
+ "void main(void) {\n"
+ " gl_Position = hudmatrix * vvertex;\n"
+ " color = vcolor;\n"
+ "}\n",
+ "varying vec4 color;\n"
+ "void main(void) {\n"
+ " 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)
{
- 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;
+ 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)
{
- 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)
- {
- 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))
- {
- memset(vspragma, ' ', olen);
- vspragma += olen;
- char *end = vspragma + strcspn(vspragma, "\n\r");
- end += strspn(end, "\n\r");
- int endlen = strcspn(end, "\n\r");
- memset(end, ' ', endlen);
- }
- }
- 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))
- {
- memset(pspragma, ' ', olen);
- pspragma += olen;
- char *end = pspragma + strcspn(pspragma, "\n\r");
- end += strspn(end, "\n\r");
- int endlen = strcspn(end, "\n\r");
- memset(end, ' ', endlen);
- }
- }
- row += rowoffset;
- if(row < 0 || row >= MAXVARIANTROWS) return;
- int col = s.numvariants(row);
- defformatstring(varname, "<variant:%d,%d>%s", col, row, sname);
- string reuse;
- if(col) formatstring(reuse, "%d", row);
- else copystring(reuse, "");
- newshader(s.type, varname, vschanged ? vsv.getbuf() : reuse, pschanged ? psv.getbuf() : reuse, &s, row);
+ 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)
+ {
+ 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))
+ {
+ memset(vspragma, ' ', olen);
+ vspragma += olen;
+ char *end = vspragma + strcspn(vspragma, "\n\r");
+ end += strspn(end, "\n\r");
+ int endlen = strcspn(end, "\n\r");
+ memset(end, ' ', endlen);
+ }
+ }
+ 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))
+ {
+ memset(pspragma, ' ', olen);
+ pspragma += olen;
+ char *end = pspragma + strcspn(pspragma, "\n\r");
+ end += strspn(end, "\n\r");
+ int endlen = strcspn(end, "\n\r");
+ memset(end, ' ', endlen);
+ }
+ }
+ row += rowoffset;
+ if(row < 0 || row >= MAXVARIANTROWS) return;
+ int col = s.numvariants(row);
+ defformatstring(varname, "<variant:%d,%d>%s", col, row, sname);
+ string reuse;
+ if(col) formatstring(reuse, "%d", row);
+ else copystring(reuse, "");
+ newshader(s.type, varname, vschanged ? vsv.getbuf() : reuse, pschanged ? psv.getbuf() : reuse, &s, row);
}
static bool genwatervariant(Shader &s, const char *sname, const char *vs, const char *ps, int row = 2)
{
- if(!strstr(vs, "//:water") && !strstr(ps, "//:water")) return false;
-
- vector<char> vsw, psw;
-
- const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
- if(!vsmain || !vsend) return false;
- vsw.put(vs, vsmain - vs);
- const char *fadeparams = "\nuniform vec4 waterfadeparams;\nvarying float fadedepth;\n";
- vsw.put(fadeparams, strlen(fadeparams));
- vsw.put(vsmain, vsend - vsmain);
- const char *fadedef = "\nfadedepth = vvertex.z*waterfadeparams.x + waterfadeparams.y;\n";
- vsw.put(fadedef, strlen(fadedef));
- vsw.put(vsend, strlen(vsend)+1);
-
- const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
- if(!psmain || !psend) return false;
- psw.put(ps, psmain - ps);
- const char *fadeinterp = "\nvarying float fadedepth;\n";
- psw.put(fadeinterp, strlen(fadeinterp));
- psw.put(psmain, psend - psmain);
- const char *fade = "\ngl_FragColor.a = fadedepth;\n";
- psw.put(fade, strlen(fade));
- psw.put(psend, strlen(psend)+1);
-
- defformatstring(name, "<water>%s", sname);
- Shader *variant = newshader(s.type, name, vsw.getbuf(), psw.getbuf(), &s, row);
- return variant!=NULL;
+ if(!strstr(vs, "//:water") && !strstr(ps, "//:water")) return false;
+
+ vector<char> vsw, psw;
+
+ const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
+ if(!vsmain || !vsend) return false;
+ vsw.put(vs, vsmain - vs);
+ const char *fadeparams = "\nuniform vec4 waterfadeparams;\nvarying float fadedepth;\n";
+ vsw.put(fadeparams, strlen(fadeparams));
+ vsw.put(vsmain, vsend - vsmain);
+ const char *fadedef = "\nfadedepth = vvertex.z*waterfadeparams.x + waterfadeparams.y;\n";
+ vsw.put(fadedef, strlen(fadedef));
+ vsw.put(vsend, strlen(vsend)+1);
+
+ const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
+ if(!psmain || !psend) return false;
+ psw.put(ps, psmain - ps);
+ const char *fadeinterp = "\nvarying float fadedepth;\n";
+ psw.put(fadeinterp, strlen(fadeinterp));
+ psw.put(psmain, psend - psmain);
+ const char *fade = "\ngl_FragColor.a = fadedepth;\n";
+ psw.put(fade, strlen(fade));
+ psw.put(psend, strlen(psend)+1);
+
+ defformatstring(name, "<water>%s", sname);
+ Shader *variant = newshader(s.type, name, vsw.getbuf(), psw.getbuf(), &s, row);
+ return variant!=NULL;
}
bool minimizedynlighttcusage() { return glversion < 300 && maxvaryings < 48; }
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)
- {
- 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))
- {
- 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)
- {
- defformatstring(tc,
- k<numlights ?
- "dynlight%ddir = vvertex.xyz*dynlightpos[%d].w + dynlightpos[%d].xyz;\n" :
- "vec3 dynlight%ddir = dynlight0dir*dynlightpos[%d].w + dynlightpos[%d].xyz;\n",
- 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;
- if(row < 4) genwatervariant(s, name, vsdl.getbuf(), psdl.getbuf(), row+2);
- }
+ 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)
+ {
+ 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))
+ {
+ 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)
+ {
+ defformatstring(tc,
+ k<numlights ?
+ "dynlight%ddir = vvertex.xyz*dynlightpos[%d].w + dynlightpos[%d].xyz;\n" :
+ "vec3 dynlight%ddir = dynlight0dir*dynlightpos[%d].w + dynlightpos[%d].xyz;\n",
+ 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;
+ if(row < 4) genwatervariant(s, name, vsdl.getbuf(), psdl.getbuf(), row+2);
+ }
}
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";
- vssm.put(tcgen, strlen(tcgen));
- const char *sm =
- smoothshadowmappeel ?
- "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";
- pssm.put(sm, strlen(sm));
- defformatstring(smlight,
- "%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;
- genwatervariant(s, name, vssm.getbuf(), pssm.getbuf(), row+2);
-
- if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row);
+ 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";
+ vssm.put(tcgen, strlen(tcgen));
+ const char *sm =
+ smoothshadowmappeel ?
+ "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";
+ pssm.put(sm, strlen(sm));
+ defformatstring(smlight,
+ "%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;
+ genwatervariant(s, name, vssm.getbuf(), pssm.getbuf(), row+2);
+
+ if(strstr(vs, "//:dynlight")) gendynlightvariant(s, name, vssm.getbuf(), pssm.getbuf(), row);
}
static void genfogshader(vector<char> &vsbuf, vector<char> &psbuf, const char *vs, const char *ps)
{
- const char *vspragma = strstr(vs, "//:fog"), *pspragma = strstr(ps, "//:fog");
- if(!vspragma && !pspragma) return;
- static const int pragmalen = strlen("//:fog");
- const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
- if(vsmain && vsend)
- {
- vsbuf.put(vs, vsmain - vs);
- const char *fogparams = "\nuniform vec4 fogplane;\nvarying float fogcoord;\n";
- vsbuf.put(fogparams, strlen(fogparams));
- vsbuf.put(vsmain, vsend - vsmain);
- const char *vsfog = "\nfogcoord = dot(fogplane, gl_Position);\n";
- vsbuf.put(vsfog, strlen(vsfog));
- vsbuf.put(vsend, strlen(vsend)+1);
- }
- const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
- if(psmain && psend)
- {
- psbuf.put(ps, psmain - ps);
- const char *fogparams =
- "\nuniform vec3 fogcolor;\n"
- "uniform vec2 fogparams;\n"
- "varying float fogcoord;\n";
- psbuf.put(fogparams, strlen(fogparams));
- psbuf.put(psmain, psend - psmain);
- const char *psdef = "\n#define FOG_COLOR ";
- const char *psfog =
- pspragma && !strncmp(pspragma+pragmalen, "rgba", 4) ?
- "\ngl_FragColor = mix((FOG_COLOR), gl_FragColor, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n" :
- "\ngl_FragColor.rgb = mix((FOG_COLOR).rgb, gl_FragColor.rgb, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n";
- int clen = 0;
- if(pspragma)
- {
- pspragma += pragmalen;
- while(iscubealpha(*pspragma)) pspragma++;
- while(*pspragma && !iscubespace(*pspragma)) pspragma++;
- pspragma += strspn(pspragma, " \t\v\f");
- clen = strcspn(pspragma, "\r\n");
- }
- if(clen <= 0) { pspragma = "fogcolor"; clen = strlen(pspragma); }
- psbuf.put(psdef, strlen(psdef));
- psbuf.put(pspragma, clen);
- psbuf.put(psfog, strlen(psfog));
- psbuf.put(psend, strlen(psend)+1);
- }
+ const char *vspragma = strstr(vs, "//:fog"), *pspragma = strstr(ps, "//:fog");
+ if(!vspragma && !pspragma) return;
+ static const int pragmalen = strlen("//:fog");
+ const char *vsmain = findglslmain(vs), *vsend = strrchr(vs, '}');
+ if(vsmain && vsend)
+ {
+ vsbuf.put(vs, vsmain - vs);
+ const char *fogparams = "\nuniform vec4 fogplane;\nvarying float fogcoord;\n";
+ vsbuf.put(fogparams, strlen(fogparams));
+ vsbuf.put(vsmain, vsend - vsmain);
+ const char *vsfog = "\nfogcoord = dot(fogplane, gl_Position);\n";
+ vsbuf.put(vsfog, strlen(vsfog));
+ vsbuf.put(vsend, strlen(vsend)+1);
+ }
+ const char *psmain = findglslmain(ps), *psend = strrchr(ps, '}');
+ if(psmain && psend)
+ {
+ psbuf.put(ps, psmain - ps);
+ const char *fogparams =
+ "\nuniform vec3 fogcolor;\n"
+ "uniform vec2 fogparams;\n"
+ "varying float fogcoord;\n";
+ psbuf.put(fogparams, strlen(fogparams));
+ psbuf.put(psmain, psend - psmain);
+ const char *psdef = "\n#define FOG_COLOR ";
+ const char *psfog =
+ pspragma && !strncmp(pspragma+pragmalen, "rgba", 4) ?
+ "\ngl_FragColor = mix((FOG_COLOR), gl_FragColor, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n" :
+ "\ngl_FragColor.rgb = mix((FOG_COLOR).rgb, gl_FragColor.rgb, clamp(fogcoord*fogparams.x + fogparams.y, 0.0, 1.0));\n";
+ int clen = 0;
+ if(pspragma)
+ {
+ pspragma += pragmalen;
+ while(iscubealpha(*pspragma)) pspragma++;
+ while(*pspragma && !iscubespace(*pspragma)) pspragma++;
+ pspragma += strspn(pspragma, " \t\v\f");
+ clen = strcspn(pspragma, "\r\n");
+ }
+ if(clen <= 0) { pspragma = "fogcolor"; clen = strlen(pspragma); }
+ psbuf.put(psdef, strlen(psdef));
+ psbuf.put(pspragma, clen);
+ psbuf.put(psfog, strlen(psfog));
+ psbuf.put(psend, strlen(psend)+1);
+ }
}
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)
- {
- defformatstring(uni, "\nuniform vec4 %s;\n", variant->defaultparams[i].name);
- vsbuf.put(uni, strlen(uni));
- psbuf.put(uni, strlen(uni));
- }
- else loopv(slotparams)
- {
- defformatstring(uni, "\nuniform vec4 %s;\n", slotparams[i].name);
- vsbuf.put(uni, strlen(uni));
- psbuf.put(uni, strlen(uni));
- }
- vsbuf.put(vsmain, strlen(vsmain)+1);
- psbuf.put(psmain, strlen(psmain)+1);
+ 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)
+ {
+ defformatstring(uni, "\nuniform vec4 %s;\n", variant->defaultparams[i].name);
+ vsbuf.put(uni, strlen(uni));
+ psbuf.put(uni, strlen(uni));
+ }
+ else loopv(slotparams)
+ {
+ defformatstring(uni, "\nuniform vec4 %s;\n", slotparams[i].name);
+ vsbuf.put(uni, strlen(uni));
+ psbuf.put(uni, strlen(uni));
+ }
+ vsbuf.put(vsmain, strlen(vsmain)+1);
+ psbuf.put(psmain, strlen(psmain)+1);
}
VAR(defershaders, 0, 1, 1);
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; }
- char *rname = exists ? exists->name : newstring(name);
- Shader &s = shaders[rname];
- s.name = rname;
- DELETEA(s.defer);
- s.defer = newstring(contents);
- s.type = SHADER_DEFERRED | *type;
- s.standard = standardshaders;
+ Shader *exists = shaders.access(name);
+ if(exists && !exists->invalid()) return;
+ if(!defershaders) { execute(contents); return; }
+ char *rname = exists ? exists->name : newstring(name);
+ Shader &s = shaders[rname];
+ s.name = rname;
+ DELETEA(s.defer);
+ s.defer = newstring(contents);
+ s.type = SHADER_DEFERRED | *type;
+ s.standard = standardshaders;
}
void Shader::force()
{
- if(!deferred() || !defer) return;
-
- char *cmd = defer;
- defer = NULL;
- bool wasstandard = standardshaders, wasforcing = forceshaders;
- int oldflags = identflags;
- standardshaders = standard;
- forceshaders = false;
- identflags &= ~IDF_PERSIST;
- slotparams.shrink(0);
- execute(cmd);
- identflags = oldflags;
- forceshaders = wasforcing;
- standardshaders = wasstandard;
- delete[] cmd;
-
- if(deferred())
- {
- DELETEA(defer);
- type = SHADER_INVALID;
- }
+ if(!deferred() || !defer) return;
+
+ char *cmd = defer;
+ defer = NULL;
+ bool wasstandard = standardshaders, wasforcing = forceshaders;
+ int oldflags = identflags;
+ standardshaders = standard;
+ forceshaders = false;
+ identflags &= ~IDF_PERSIST;
+ slotparams.shrink(0);
+ execute(cmd);
+ identflags = oldflags;
+ forceshaders = wasforcing;
+ standardshaders = wasstandard;
+ delete[] cmd;
+
+ if(deferred())
+ {
+ DELETEA(defer);
+ type = SHADER_INVALID;
+ }
}
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();
+ // 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()
{
- static int version = 0;
- if(++version >= 0) return version;
- version = 0;
- enumerate(shaders, Shader, s, { loopvj(s.uniformlocs) s.uniformlocs[j].version = -1; });
- return version;
+ static int version = 0;
+ if(++version >= 0) return version;
+ version = 0;
+ enumerate(shaders, Shader, s, { loopvj(s.uniformlocs) s.uniformlocs[j].version = -1; });
+ return version;
}
VARFP(shaderdetail, 0, MAXSHADERDETAIL, MAXSHADERDETAIL, fixshaderdetail());
void Shader::fixdetailshader(bool shouldforce, bool recurse)
{
- Shader *alt = this;
- detailshader = NULL;
- do
- {
- Shader *cur = shaderdetail < MAXSHADERDETAIL ? alt->fastshader[shaderdetail] : alt;
- if(cur->deferred() && shouldforce) cur->force();
- 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 *alt = this;
+ detailshader = NULL;
+ do
+ {
+ Shader *cur = shaderdetail < MAXSHADERDETAIL ? alt->fastshader[shaderdetail] : alt;
+ if(cur->deferred() && shouldforce) cur->force();
+ 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 *s = shaders.access(name);
- if(!s) return NULL;
- if(!s->detailshader) s->fixdetailshader();
- s->forced = true;
- return s;
+ Shader *s = shaders.access(name);
+ if(!s) return NULL;
+ if(!s->detailshader) s->fixdetailshader();
+ s->forced = true;
+ return s;
}
void shader(int *type, char *name, char *vs, char *ps)
{
- if(lookupshaderbyname(name)) return;
-
- defformatstring(info, "shader %s", name);
- renderprogress(loadprogress, info);
+ if(lookupshaderbyname(name)) return;
+
+ defformatstring(info, "shader %s", name);
+ renderprogress(loadprogress, info);
- vector<char> vsbuf, psbuf, vsbak, psbak;
+ vector<char> vsbuf, psbuf, vsbak, psbak;
#define GENSHADER(cond, body) \
- 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; \
- if(vsbuf.length()) vs = vsbuf.getbuf(); \
- if(psbuf.length()) ps = psbuf.getbuf(); \
- }
- GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps));
- GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
- Shader *s = newshader(*type, name, vs, ps);
- if(s)
- {
- if(strstr(vs, "//:water")) genwatervariant(*s, s->name, vs, ps);
- if(strstr(vs, "//:shadowmap")) genshadowmapvariant(*s, s->name, vs, ps);
- if(strstr(vs, "//:dynlight")) gendynlightvariant(*s, s->name, vs, ps);
- }
- slotparams.shrink(0);
+ 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; \
+ if(vsbuf.length()) vs = vsbuf.getbuf(); \
+ if(psbuf.length()) ps = psbuf.getbuf(); \
+ }
+ GENSHADER(slotparams.length(), genuniformdefs(vsbuf, psbuf, vs, ps));
+ GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
+ Shader *s = newshader(*type, name, vs, ps);
+ if(s)
+ {
+ if(strstr(vs, "//:water")) genwatervariant(*s, s->name, vs, ps);
+ 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)
- {
- 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));
- GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
- Shader *v = newshader(*type, varname, vs, ps, s, *row);
- 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);
- }
+ 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));
+ GENSHADER(strstr(vs, "//:fog") || strstr(ps, "//:fog"), genfogshader(vsbuf, psbuf, vs, ps));
+ Shader *v = newshader(*type, varname, vs, ps, s, *row);
+ 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)
{
- slotparams.shrink(0);
- Shader *s = shaders.access(name);
- if(!s)
- {
- conoutf(CON_ERROR, "no such shader: %s", name);
- }
- else slotshader = s;
+ slotparams.shrink(0);
+ Shader *s = shaders.access(name);
+ if(!s)
+ {
+ conoutf(CON_ERROR, "no such shader: %s", name);
+ }
+ else slotshader = s;
}
void resetslotshader()
{
- slotshader = NULL;
- slotparams.shrink(0);
+ slotshader = NULL;
+ slotparams.shrink(0);
}
void setslotshader(Slot &s)
{
- s.shader = slotshader;
- if(!s.shader)
- {
- s.shader = stdworldshader;
- return;
- }
- loopv(slotparams) s.params.add(slotparams[i]);
+ s.shader = slotshader;
+ 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)
- {
- int loc = -1;
- SlotShaderParam &param = params[i];
- loopv(sh->defaultparams)
- {
- SlotShaderParamState &dparam = sh->defaultparams[i];
- if(dparam.name==param.name)
- {
- if(memcmp(param.val, dparam.val, sizeof(param.val))) loc = i;
- break;
- }
- }
- param.loc = loc;
- }
- else if(load) loopv(params) params[i].loc = -1;
+ if(sh) loopv(params)
+ {
+ int loc = -1;
+ SlotShaderParam &param = params[i];
+ loopv(sh->defaultparams)
+ {
+ SlotShaderParamState &dparam = sh->defaultparams[i];
+ if(dparam.name==param.name)
+ {
+ if(memcmp(param.val, dparam.val, sizeof(param.val))) loc = i;
+ break;
+ }
+ }
+ param.loc = loc;
+ }
+ else if(load) loopv(params) params[i].loc = -1;
}
void linkslotshader(Slot &s, bool load)
{
- if(!s.shader) return;
+ if(!s.shader) return;
- if(load && !s.shader->detailshader) s.shader->fixdetailshader();
+ if(load && !s.shader->detailshader) s.shader->fixdetailshader();
- linkslotshaderparams(s.params, s.shader->detailshader, load);
+ linkslotshaderparams(s.params, s.shader->detailshader, load);
}
void linkvslotshader(VSlot &s, bool load)
{
- if(!s.slot->shader) return;
+ if(!s.slot->shader) return;
- Shader *sh = s.slot->shader->detailshader;
- linkslotshaderparams(s.params, sh, load);
+ Shader *sh = s.slot->shader->detailshader;
+ linkslotshaderparams(s.params, sh, load);
- if(!sh) return;
+ if(!sh) return;
- if(s.slot->texmask&(1<<TEX_GLOW))
- {
- static const char *paramname = getshaderparamname("glowcolor");
- const float *param = findslotparam(s, paramname);
- if(param) s.glowcolor = vec(param).clamp(0, 1);
- }
+ if(s.slot->texmask&(1<<TEX_GLOW))
+ {
+ static const char *paramname = getshaderparamname("glowcolor");
+ const float *param = findslotparam(s, paramname);
+ if(param) s.glowcolor = vec(param).clamp(0, 1);
+ }
}
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);
+ 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)
{
- Shader *ns = shaders.access(nice), *fs = shaders.access(fast);
- if(!ns || !fs) return;
- loopi(min(*detail+1, MAXSHADERDETAIL)) ns->fastshader[i] = fs;
- ns->fixdetailshader(false);
+ Shader *ns = shaders.access(nice), *fs = shaders.access(fast);
+ if(!ns || !fs) return;
+ loopi(min(*detail+1, MAXSHADERDETAIL)) ns->fastshader[i] = fs;
+ ns->fixdetailshader(false);
}
COMMAND(shader, "isss");
@@ -1233,28 +1228,28 @@ static hashset<const char *> shaderparamnames(256);
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));
+ 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)
{
- if(name) name = getshaderparamname(name);
- loopv(slotparams)
- {
- SlotShaderParam &param = slotparams[i];
- if(param.name==name)
- {
- param.val[0] = x;
- param.val[1] = y;
- param.val[2] = z;
- param.val[3] = w;
- return;
- }
- }
- SlotShaderParam param = {name, -1, {x, y, z, w}};
- slotparams.add(param);
+ if(name) name = getshaderparamname(name);
+ loopv(slotparams)
+ {
+ SlotShaderParam &param = slotparams[i];
+ if(param.name==name)
+ {
+ param.val[0] = x;
+ param.val[1] = y;
+ param.val[2] = z;
+ param.val[3] = w;
+ return;
+ }
+ }
+ SlotShaderParam param = {name, -1, {x, y, z, w}};
+ slotparams.add(param);
}
ICOMMAND(setuniformparam, "sffff", (char *name, float *x, float *y, float *z, float *w), addslotparam(name, *x, *y, *z, *w));
@@ -1265,10 +1260,10 @@ ICOMMAND(defuniformparam, "sffff", (char *name, float *x, float *y, float *z, fl
struct postfxtex
{
- GLuint id;
- int scale, used;
+ GLuint id;
+ int scale, used;
- postfxtex() : id(0), scale(0), used(-1) {}
+ postfxtex() : id(0), scale(0), used(-1) {}
};
vector<postfxtex> postfxtexs;
int postfxbinds[NUMPOSTFXBINDS];
@@ -1277,246 +1272,246 @@ int postfxw = 0, postfxh = 0;
struct postfxpass
{
- Shader *shader;
- vec4 params;
- uint inputs, freeinputs;
- int outputbind, outputscale;
+ Shader *shader;
+ vec4 params;
+ uint inputs, freeinputs;
+ int outputbind, outputscale;
- postfxpass() : shader(NULL), inputs(1), freeinputs(1), outputbind(0), outputscale(0) {}
+ postfxpass() : shader(NULL), inputs(1), freeinputs(1), outputbind(0), outputscale(0) {}
};
vector<postfxpass> postfxpasses;
static int allocatepostfxtex(int scale)
{
- loopv(postfxtexs)
- {
- postfxtex &t = postfxtexs[i];
- if(t.scale==scale && t.used < 0) return i;
- }
- postfxtex &t = postfxtexs.add();
- t.scale = scale;
- glGenTextures(1, &t.id);
- createtexture(t.id, max(screenw>>scale, 1), max(screenh>>scale, 1), NULL, 3, 1, GL_RGB);
- return postfxtexs.length()-1;
+ loopv(postfxtexs)
+ {
+ postfxtex &t = postfxtexs[i];
+ if(t.scale==scale && t.used < 0) return i;
+ }
+ postfxtex &t = postfxtexs.add();
+ t.scale = scale;
+ glGenTextures(1, &t.id);
+ createtexture(t.id, max(screenw>>scale, 1), max(screenh>>scale, 1), NULL, 3, 1, GL_RGB);
+ return postfxtexs.length()-1;
}
void cleanuppostfx(bool fullclean)
{
- if(fullclean && postfxfb)
- {
- glDeleteFramebuffers_(1, &postfxfb);
- postfxfb = 0;
- }
+ if(fullclean && postfxfb)
+ {
+ glDeleteFramebuffers_(1, &postfxfb);
+ postfxfb = 0;
+ }
- loopv(postfxtexs) glDeleteTextures(1, &postfxtexs[i].id);
- postfxtexs.shrink(0);
+ loopv(postfxtexs) glDeleteTextures(1, &postfxtexs[i].id);
+ postfxtexs.shrink(0);
- postfxw = 0;
- postfxh = 0;
+ postfxw = 0;
+ postfxh = 0;
}
void renderpostfx()
{
- if(postfxpasses.empty()) return;
-
- if(postfxw != screenw || postfxh != screenh)
- {
- cleanuppostfx(false);
- postfxw = screenw;
- postfxh = screenh;
- }
-
- int binds[NUMPOSTFXBINDS];
- loopi(NUMPOSTFXBINDS) binds[i] = -1;
- loopv(postfxtexs) postfxtexs[i].used = -1;
-
- binds[0] = allocatepostfxtex(0);
- postfxtexs[binds[0]].used = 0;
- glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[0]].id);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenw, screenh);
-
- if(postfxpasses.length() > 1)
- {
- if(!postfxfb) glGenFramebuffers_(1, &postfxfb);
- glBindFramebuffer_(GL_FRAMEBUFFER, postfxfb);
- }
-
- GLOBALPARAMF(millis, lastmillis/1000.0f);
-
- loopv(postfxpasses)
- {
- postfxpass &p = postfxpasses[i];
-
- int tex = -1;
- if(!postfxpasses.inrange(i+1))
- {
- if(postfxpasses.length() > 1) glBindFramebuffer_(GL_FRAMEBUFFER, 0);
- }
- else
- {
- tex = allocatepostfxtex(p.outputscale);
- glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, postfxtexs[tex].id, 0);
- }
-
- int w = tex >= 0 ? max(screenw>>postfxtexs[tex].scale, 1) : screenw,
- h = tex >= 0 ? max(screenh>>postfxtexs[tex].scale, 1) : screenh;
- glViewport(0, 0, w, h);
- p.shader->set();
- LOCALPARAM(params, p.params);
- int tw = w, th = h, tmu = 0;
- loopj(NUMPOSTFXBINDS) if(p.inputs&(1<<j) && binds[j] >= 0)
- {
- if(!tmu)
- {
- tw = max(screenw>>postfxtexs[binds[j]].scale, 1);
- th = max(screenh>>postfxtexs[binds[j]].scale, 1);
- }
- else glActiveTexture_(GL_TEXTURE0 + tmu);
- glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[j]].id);
- ++tmu;
- }
- if(tmu) glActiveTexture_(GL_TEXTURE0);
- LOCALPARAMF(postfxscale, 1.0f/tw, 1.0f/th);
- screenquad(1, 1);
-
- loopj(NUMPOSTFXBINDS) if(p.freeinputs&(1<<j) && binds[j] >= 0)
- {
- postfxtexs[binds[j]].used = -1;
- binds[j] = -1;
- }
- if(tex >= 0)
- {
- if(binds[p.outputbind] >= 0) postfxtexs[binds[p.outputbind]].used = -1;
- binds[p.outputbind] = tex;
- postfxtexs[tex].used = p.outputbind;
- }
- }
+ if(postfxpasses.empty()) return;
+
+ if(postfxw != screenw || postfxh != screenh)
+ {
+ cleanuppostfx(false);
+ postfxw = screenw;
+ postfxh = screenh;
+ }
+
+ int binds[NUMPOSTFXBINDS];
+ loopi(NUMPOSTFXBINDS) binds[i] = -1;
+ loopv(postfxtexs) postfxtexs[i].used = -1;
+
+ binds[0] = allocatepostfxtex(0);
+ postfxtexs[binds[0]].used = 0;
+ glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[0]].id);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenw, screenh);
+
+ if(postfxpasses.length() > 1)
+ {
+ if(!postfxfb) glGenFramebuffers_(1, &postfxfb);
+ glBindFramebuffer_(GL_FRAMEBUFFER, postfxfb);
+ }
+
+ GLOBALPARAMF(millis, lastmillis/1000.0f);
+
+ loopv(postfxpasses)
+ {
+ postfxpass &p = postfxpasses[i];
+
+ int tex = -1;
+ if(!postfxpasses.inrange(i+1))
+ {
+ if(postfxpasses.length() > 1) glBindFramebuffer_(GL_FRAMEBUFFER, 0);
+ }
+ else
+ {
+ tex = allocatepostfxtex(p.outputscale);
+ glFramebufferTexture2D_(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, postfxtexs[tex].id, 0);
+ }
+
+ int w = tex >= 0 ? max(screenw>>postfxtexs[tex].scale, 1) : screenw,
+ h = tex >= 0 ? max(screenh>>postfxtexs[tex].scale, 1) : screenh;
+ glViewport(0, 0, w, h);
+ p.shader->set();
+ LOCALPARAM(params, p.params);
+ int tw = w, th = h, tmu = 0;
+ loopj(NUMPOSTFXBINDS) if(p.inputs&(1<<j) && binds[j] >= 0)
+ {
+ if(!tmu)
+ {
+ tw = max(screenw>>postfxtexs[binds[j]].scale, 1);
+ th = max(screenh>>postfxtexs[binds[j]].scale, 1);
+ }
+ else glActiveTexture_(GL_TEXTURE0 + tmu);
+ glBindTexture(GL_TEXTURE_2D, postfxtexs[binds[j]].id);
+ ++tmu;
+ }
+ if(tmu) glActiveTexture_(GL_TEXTURE0);
+ LOCALPARAMF(postfxscale, 1.0f/tw, 1.0f/th);
+ screenquad(1, 1);
+
+ loopj(NUMPOSTFXBINDS) if(p.freeinputs&(1<<j) && binds[j] >= 0)
+ {
+ postfxtexs[binds[j]].used = -1;
+ binds[j] = -1;
+ }
+ if(tex >= 0)
+ {
+ if(binds[p.outputbind] >= 0) postfxtexs[binds[p.outputbind]].used = -1;
+ binds[p.outputbind] = tex;
+ postfxtexs[tex].used = p.outputbind;
+ }
+ }
}
static bool addpostfx(const char *name, int outputbind, int outputscale, uint inputs, uint freeinputs, const vec4 &params)
{
- if(!*name) return false;
- Shader *s = useshaderbyname(name);
- if(!s)
- {
- conoutf(CON_ERROR, "no such postfx shader: %s", name);
- return false;
- }
- postfxpass &p = postfxpasses.add();
- p.shader = s;
- p.outputbind = outputbind;
- p.outputscale = outputscale;
- p.inputs = inputs;
- p.freeinputs = freeinputs;
- p.params = params;
- return true;
+ if(!*name) return false;
+ Shader *s = useshaderbyname(name);
+ if(!s)
+ {
+ conoutf(CON_ERROR, "no such postfx shader: %s", name);
+ return false;
+ }
+ postfxpass &p = postfxpasses.add();
+ p.shader = s;
+ p.outputbind = outputbind;
+ p.outputscale = outputscale;
+ p.inputs = inputs;
+ p.freeinputs = freeinputs;
+ p.params = params;
+ return true;
}
void clearpostfx()
{
- postfxpasses.shrink(0);
- cleanuppostfx(false);
+ postfxpasses.shrink(0);
+ cleanuppostfx(false);
}
COMMAND(clearpostfx, "");
ICOMMAND(addpostfx, "siisffff", (char *name, int *bind, int *scale, char *inputs, float *x, float *y, float *z, float *w),
{
- int inputmask = inputs[0] ? 0 : 1;
- int freemask = inputs[0] ? 0 : 1;
- bool freeinputs = true;
- for(; *inputs; inputs++) if(isdigit(*inputs))
- {
- inputmask |= 1<<(*inputs-'0');
- if(freeinputs) freemask |= 1<<(*inputs-'0');
- }
- else if(*inputs=='+') freeinputs = false;
- else if(*inputs=='-') freeinputs = true;
- inputmask &= (1<<NUMPOSTFXBINDS)-1;
- freemask &= (1<<NUMPOSTFXBINDS)-1;
- addpostfx(name, clamp(*bind, 0, NUMPOSTFXBINDS-1), max(*scale, 0), inputmask, freemask, vec4(*x, *y, *z, *w));
+ int inputmask = inputs[0] ? 0 : 1;
+ int freemask = inputs[0] ? 0 : 1;
+ bool freeinputs = true;
+ for(; *inputs; inputs++) if(isdigit(*inputs))
+ {
+ inputmask |= 1<<(*inputs-'0');
+ if(freeinputs) freemask |= 1<<(*inputs-'0');
+ }
+ else if(*inputs=='+') freeinputs = false;
+ else if(*inputs=='-') freeinputs = true;
+ inputmask &= (1<<NUMPOSTFXBINDS)-1;
+ freemask &= (1<<NUMPOSTFXBINDS)-1;
+ addpostfx(name, clamp(*bind, 0, NUMPOSTFXBINDS-1), max(*scale, 0), inputmask, freemask, vec4(*x, *y, *z, *w));
});
ICOMMAND(setpostfx, "sffff", (char *name, float *x, float *y, float *z, float *w),
{
- clearpostfx();
- if(name[0]) addpostfx(name, 0, 0, 1, 1, vec4(*x, *y, *z, *w));
+ clearpostfx();
+ if(name[0]) addpostfx(name, 0, 0, 1, 1, vec4(*x, *y, *z, *w));
});
void cleanupshaders()
{
- cleanuppostfx(true);
+ cleanuppostfx(true);
- loadedshaders = false;
- nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = foggedshader = foggednotextureshader = stdworldshader = NULL;
- enumerate(shaders, Shader, s, s.cleanup());
- Shader::lastshader = NULL;
- glUseProgram_(0);
+ loadedshaders = false;
+ nullshader = hudshader = hudnotextureshader = textureshader = notextureshader = nocolorshader = foggedshader = foggednotextureshader = stdworldshader = NULL;
+ enumerate(shaders, Shader, s, s.cleanup());
+ Shader::lastshader = NULL;
+ glUseProgram_(0);
}
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)
- {
- defformatstring(info, "shader %s", s.name);
- renderprogress(0.0, info);
- if(!s.compile()) s.cleanup(true);
- loopv(s.variants)
- {
- Shader *v = s.variants[i];
- if((v->reusevs && v->reusevs->invalid()) ||
- (v->reuseps && v->reuseps->invalid()) ||
- !v->compile())
- v->cleanup(true);
- }
- }
- if(s.forced && !s.detailshader) s.fixdetailshader();
- });
+ identflags &= ~IDF_PERSIST;
+ loadshaders();
+ identflags |= IDF_PERSIST;
+ linkslotshaders();
+ 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)
+ {
+ Shader *v = s.variants[i];
+ if((v->reusevs && v->reusevs->invalid()) ||
+ (v->reuseps && v->reuseps->invalid()) ||
+ !v->compile())
+ v->cleanup(true);
+ }
+ }
+ if(s.forced && !s.detailshader) s.fixdetailshader();
+ });
}
void setupblurkernel(int radius, float sigma, float *weights, float *offsets)
{
- if(radius<1 || radius>MAXBLURRADIUS) return;
- sigma *= 2*radius;
- float total = 1.0f/sigma;
- weights[0] = total;
- 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)
- {
- 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,
- offset = 2*i+1 + weight2 / scale;
- weights[i+1] = scale;
- offsets[i+1] = offset;
- total += 2*scale;
- }
- loopi(radius+1) weights[i] /= total;
- for(int i = radius+1; i <= MAXBLURRADIUS; i++) weights[i] = offsets[i] = 0;
+ if(radius<1 || radius>MAXBLURRADIUS) return;
+ sigma *= 2*radius;
+ float total = 1.0f/sigma;
+ weights[0] = total;
+ 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)
+ {
+ 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,
+ offset = 2*i+1 + weight2 / scale;
+ weights[i+1] = scale;
+ offsets[i+1] = offset;
+ total += 2*scale;
+ }
+ loopi(radius+1) weights[i] /= total;
+ 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)
{
- 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)
- {
- defformatstring(name, "blur%c%d", 'x'+pass, radius);
- s = lookupshaderbyname(name);
- }
- s->set();
- LOCALPARAMV(weights, weights, 8);
- float scaledoffsets[8];
- loopk(8) scaledoffsets[k] = offsets[k]/size;
- LOCALPARAMV(offsets, scaledoffsets, 8);
+ 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)
+ {
+ defformatstring(name, "blur%c%d", 'x'+pass, radius);
+ s = lookupshaderbyname(name);
+ }
+ s->set();
+ LOCALPARAMV(weights, weights, 8);
+ float scaledoffsets[8];
+ loopk(8) scaledoffsets[k] = offsets[k]/size;
+ LOCALPARAMV(offsets, scaledoffsets, 8);
}