commit 3a85c12f0accf7d80ada058144ed23bd5db6f2ff
parent cd82c62716831100266a005836323ce0838b52b8
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 4 Sep 2013 03:58:56 -0700
shaders/effects: allow #defines to be passed in at compilation
- Effects may be invoked by effectname+FOO+BAR which will cause
#define FOO
#define BAR
to be inserted into the shader source after the common and global parts
- *Shader::load() takes a second defines paramter to make this happen
Diffstat:
3 files changed, 59 insertions(+), 27 deletions(-)
diff --git a/common/Effect.cc b/common/Effect.cc
@@ -15,6 +15,7 @@
#include <string>
+#include "util.h"
#include "Effect.h"
void Effect::apply(void) {
@@ -22,14 +23,43 @@ void Effect::apply(void) {
}
int Effect::init(const char *name) {
- std::string vname(name);
- std::string fname(name);
- vname.append(".vertex");
- fname.append(".fragment");
- if (vs.load(vname.c_str()))
- return -1;
- if (ps.load(fname.c_str()))
- return -1;
+ const char *x = strchr(name, '+');
+ if (x) {
+ std::string vname(name, x - name);
+ std::string fname(name, x - name);
+ vname.append(".vertex");
+ fname.append(".fragment");
+ x++;
+ std::string defines;
+ while (*x) {
+ const char *n = x;
+ x = strchr(n, '+');
+ defines.append("#define ");
+ if (x) {
+ defines.append(n, x-n);
+ defines.append("\n");
+ x++;
+ } else {
+ defines.append(n);
+ defines.append("\n");
+ break;
+ }
+ }
+ printx("EXTRAS---\n%s",defines.c_str());
+ if (vs.load(vname.c_str(), defines.c_str()))
+ return -1;
+ if (ps.load(fname.c_str(), defines.c_str()))
+ return -1;
+ } else {
+ std::string vname(name);
+ std::string fname(name);
+ vname.append(".vertex");
+ fname.append(".fragment");
+ if (vs.load(vname.c_str()))
+ return -1;
+ if (ps.load(fname.c_str()))
+ return -1;
+ }
if (pgm.link(&vs, &ps))
return -1;
return 0;
diff --git a/common/core.h b/common/core.h
@@ -55,21 +55,21 @@ struct VertexShader {
unsigned id;
VertexShader() : id(0) {};
~VertexShader() { if (id) { glDeleteShader(id); } };
- int load(const char *fn);
+ int load(const char *fn, const char *defines = "");
};
struct PixelShader {
unsigned id;
PixelShader() : id(0) {};
~PixelShader() { if (id) glDeleteShader(id); };
- int load(const char *fn);
+ int load(const char *fn, const char *defines = "");
};
struct GeometryShader {
unsigned id;
GeometryShader() : id(0) {};
~GeometryShader() { if (id) glDeleteShader(id); };
- int load(const char *fn);
+ int load(const char *fn, const char *defines = "");
};
struct Program {
diff --git a/common/shaders.cc b/common/shaders.cc
@@ -252,10 +252,10 @@ static struct source *load_shader_source(const char *fn) {
return src;
}
-static int compile_shader_source(source *src, const char *name, unsigned id) {
+static int compile_shader_source(source *src, const char *name, const char *defines, unsigned id) {
char misc[128];
- const char *data[4];
- int size[4];
+ const char *data[5];
+ int size[5];
section *part;
for (part = src->sections; part; part = part->next) {
@@ -267,18 +267,20 @@ static int compile_shader_source(source *src, const char *name, unsigned id) {
size[0] = src->common.len;
data[1] = shader_globals;
size[1] = strlen(shader_globals);
- data[2] = misc;
- size[2] = strlen(misc);
- data[3] = part->str;
- size[3] = part->len;
- glShaderSource(id, 4, data, size);
+ data[2] = defines;
+ size[2] = strlen(defines);
+ data[3] = misc;
+ size[3] = strlen(misc);
+ data[4] = part->str;
+ size[4] = part->len;
+ glShaderSource(id, 5, data, size);
return 0;
}
}
return error("cannot find section '%s'", name);
}
-static int _load_shader(unsigned *out, const char *fn, unsigned type) {
+static int _load_shader(unsigned *out, const char *fn, const char *defines, unsigned type) {
unsigned id;
source *src;
const char *x;
@@ -294,7 +296,7 @@ static int _load_shader(unsigned *out, const char *fn, unsigned type) {
return error("cannot load shader source '%s'", fn);
id = glCreateShader(type);
- if (compile_shader_source(src, x, id)) {
+ if (compile_shader_source(src, x, defines, id)) {
glDeleteShader(id);
return -1;
}
@@ -311,15 +313,15 @@ static int _load_shader(unsigned *out, const char *fn, unsigned type) {
return 0;
}
-int VertexShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_VERTEX_SHADER);
+int VertexShader::load(const char *fn, const char *defines) {
+ return _load_shader(&id, fn, defines, GL_VERTEX_SHADER);
}
-int PixelShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_FRAGMENT_SHADER);
+int PixelShader::load(const char *fn, const char *defines) {
+ return _load_shader(&id, fn, defines, GL_FRAGMENT_SHADER);
}
-int GeometryShader::load(const char *fn) {
- return _load_shader(&id, fn, GL_GEOMETRY_SHADER);
+int GeometryShader::load(const char *fn, const char *defines) {
+ return _load_shader(&id, fn, defines, GL_GEOMETRY_SHADER);
}