Line data Source code
1 : #ifndef SHADERPARAM_H_
2 : #define SHADERPARAM_H_
3 :
4 : struct UniformLoc
5 : {
6 : const char *name, *blockname;
7 : GLint loc;
8 : int version, binding, stride, offset;
9 : GLint size;
10 : const void *data;
11 0 : UniformLoc(const char *name = nullptr, const char *blockname = nullptr, int binding = -1, int stride = -1) : name(name), blockname(blockname), loc(-1), version(-1), binding(binding), stride(stride), offset(-1), size(-1), data(nullptr) {}
12 : };
13 :
14 : struct GlobalShaderParamState
15 : {
16 : union
17 : {
18 : GLfloat fval[32];
19 : GLint ival[32];
20 : GLuint uval[32];
21 : std::array<uchar, 32*sizeof(float)> buf;
22 : };
23 : int version;
24 :
25 : static int nextversion;
26 :
27 : void resetversions();
28 :
29 0 : void changed()
30 : {
31 0 : if(++nextversion < 0)
32 : {
33 0 : resetversions();
34 : }
35 0 : version = nextversion;
36 0 : }
37 : };
38 :
39 : extern std::map<std::string, GlobalShaderParamState> globalparams;
40 : extern GlobalShaderParamState *getglobalparam(const char *name);
41 :
42 : struct ShaderParamBinding
43 : {
44 : GLint loc;
45 : GLsizei size;
46 : GLenum format;
47 :
48 : ShaderParamBinding(GLint loc, GLsizei size, GLenum format);
49 0 : ShaderParamBinding() {};
50 : };
51 :
52 : struct GlobalShaderParamUse : ShaderParamBinding
53 : {
54 :
55 : const GlobalShaderParamState *param;
56 : int version;
57 :
58 : GlobalShaderParamUse(GLint loc, GLsizei size, GLenum format, const GlobalShaderParamState *param, int version);
59 : void flush();
60 : };
61 :
62 : struct LocalShaderParamState : ShaderParamBinding
63 : {
64 : std::string name;
65 :
66 0 : LocalShaderParamState() {}
67 : LocalShaderParamState(GLint loc, GLsizei size, GLenum format);
68 :
69 : };
70 :
71 : struct SlotShaderParamState : LocalShaderParamState
72 : {
73 : int flags;
74 : std::array<float, 4> val;
75 :
76 : SlotShaderParamState() {}
77 1 : SlotShaderParamState(const SlotShaderParam &p) : LocalShaderParamState(-1, 1, GL_FLOAT_VEC4)
78 : {
79 1 : name = p.name;
80 1 : flags = p.flags;
81 1 : std::memcpy(val.data(), p.val, sizeof(val));
82 1 : }
83 : };
84 :
85 : //a container containing a GLSL shader
86 : class Shader
87 : {
88 : public:
89 : static Shader *lastshader; //the current shader being used by glUseProgram()
90 :
91 : char *name, //name of the shader in shaders list
92 : *defer; //deferred shader contents
93 : int type; //type of shader, e.g. world, refractive, deferred, see enum
94 : GLuint program; //handle for GL program object
95 : std::vector<SlotShaderParamState> defaultparams;
96 : std::vector<GlobalShaderParamUse> globalparams;
97 : std::vector<LocalShaderParamState> localparams;
98 : std::vector<uchar> localparamremap;
99 : const Shader *variantshader;
100 : std::vector<Shader *> variants;
101 : bool standard, forced;
102 : std::vector<UniformLoc> uniformlocs;
103 :
104 : const void *owner;
105 :
106 : Shader();
107 : ~Shader();
108 :
109 : void flushparams();
110 : void force();
111 : bool invalid() const;
112 : bool deferred() const;
113 : bool loaded() const;
114 : bool isdynamic() const;
115 : int numvariants(int row) const;
116 : void addvariant(int row, Shader *s);
117 : void setvariant(int col, int row);
118 : void setvariant(int col, int row, const Slot &slot);
119 : void setvariant(int col, int row, const Slot &slot, const VSlot &vslot);
120 : void set();
121 : void set(const Slot &slot);
122 : void set(const Slot &slot, const VSlot &vslot);
123 : bool compile();
124 : void cleanup(bool full = false);
125 : void reusecleanup();
126 :
127 : static int uniformlocversion();
128 : Shader *setupshader(char *rname, const char *ps, const char *vs, Shader *variant, int row);
129 :
130 : private:
131 : char *vsstr, //a pointer to a `v`ertex `s`hader `str`ing
132 : *psstr; //a pointer to a `p`ixel `s`hader `str`ing
133 : struct AttribLoc
134 : {
135 : const char *name;
136 : int loc;
137 0 : AttribLoc(const char *name = nullptr, int loc = -1) : name(name), loc(loc) {}
138 : };
139 : std::vector<AttribLoc> attriblocs;
140 : GLuint vsobj, psobj;
141 : const Shader *reusevs, *reuseps; //may be equal to variantshader, or its getvariant()
142 : ushort *variantrows;
143 : bool used;
144 : void setslotparams(const Slot &slot);
145 : void setslotparams(const Slot &slot, const VSlot &vslot);
146 : void bindprograms();
147 : void setvariant_(int col, int row);
148 : void set_();
149 : void allocglslactiveuniforms();
150 : void setglsluniformformat(const char *name, GLenum format, int size);
151 :
152 : //attaches shaders to the Shader::program handle
153 : void linkglslprogram(bool msg = true);
154 :
155 : /**
156 : * @brief Sets an OpenGL int uniform
157 : * gets the uniform1i with name `name` and sets its value to `tmu`
158 : * no effect if no uniform with given name found
159 : */
160 : void uniformtex(std::string_view name, int tmu) const;
161 :
162 : /**
163 : * For each `//:attrib <string> <int>` found in the passed vertex shader,
164 : * adds an AttribLoc to this Shader's attriblocs comprising of a string (also stored in shaderparamnames),
165 : * and the location specified in the second parameter
166 : */
167 : void genattriblocs(const char *vs, const Shader *reusevs);
168 : void genuniformlocs(const char *vs, const Shader *reusevs, const Shader *reuseps);
169 : const Shader *getvariant(int col, int row) const;
170 : };
171 :
172 : class GlobalShaderParam
173 : {
174 : public:
175 : GlobalShaderParam(const char *name);
176 :
177 : GlobalShaderParamState &resolve();
178 : void setf(float x = 0, float y = 0, float z = 0, float w = 0);
179 : void set(const vec &v, float w = 0);
180 : void set(const vec2 &v, float z = 0, float w = 0);
181 : void set(const matrix3 &m);
182 : void set(const matrix4 &m);
183 :
184 : template<class T>
185 0 : T *reserve()
186 : {
187 0 : return reinterpret_cast<T *>(resolve().buf.data());
188 : }
189 : private:
190 : const std::string name;
191 : GlobalShaderParamState *param;
192 : GlobalShaderParamState &getglobalparam(const std::string &name) const;
193 :
194 : };
195 :
196 : class LocalShaderParam
197 : {
198 : public:
199 : LocalShaderParam(const char *name);
200 : void setf(float x = 0, float y = 0, float z = 0, float w = 0) const;
201 : void set(const vec &v, float w = 0) const;
202 : void set(const vec4<float> &v) const;
203 : void setv(const vec *v, int n = 1) const;
204 : void setv(const vec2 *v, int n = 1) const;
205 : void setv(const vec4<float> *v, int n = 1) const;
206 : void setv(const float *f, int n) const;
207 : void set(const matrix3 &m) const;
208 : void set(const matrix4 &m) const;
209 : private:
210 : void setv(const matrix3 *m, int n = 1) const;
211 : void setv(const matrix4 *m, int n = 1) const;
212 : const LocalShaderParamState *resolve() const;
213 :
214 : const char * const name;
215 : mutable int loc;
216 : };
217 :
218 : /**
219 : * @brief Defines a LocalShaderParam with static storage inside the function's scope
220 : *
221 : * This macro creates a LocalShaderParam named `param` and inserts it into the function
222 : * as a static variable. This variable cannot be accessed later and remains defined
223 : * for as long as the program runs.
224 : *
225 : * @param name a string (or plain text, that will be stringized)
226 : * @param vals the values to set, must comply with one of the set() functions for LocalShaderParam
227 : */
228 : #define LOCALPARAM(name, vals) \
229 : do \
230 : { \
231 : static LocalShaderParam param( #name ); \
232 : param.set(vals); \
233 : } \
234 : while(0)
235 :
236 : //creates a localshaderparam like above but calls setf() instead
237 : #define LOCALPARAMF(name, ...) \
238 : do \
239 : { \
240 : static LocalShaderParam param( #name ); \
241 : param.setf(__VA_ARGS__); \
242 : } while(0)
243 :
244 : #define LOCALPARAMV(name, vals, num) \
245 : do \
246 : { \
247 : static LocalShaderParam param( #name ); \
248 : param.setv(vals, num); \
249 : } while(0)
250 :
251 : //creates a globalshaderparam, either by calling set(), setf() or setv()
252 : //this will create a temp object containing #name, and then attempt to set()
253 : //it to a value in the global shader param map
254 : //overrides exist for set() for various different types
255 : #define GLOBALPARAM(name, vals) do { static GlobalShaderParam param( #name ); param.set(vals); } while(0)
256 :
257 : //same as globalparam, but takes up to 4 float args
258 : #define GLOBALPARAMF(name, ...) do { static GlobalShaderParam param( #name ); param.setf(__VA_ARGS__); } while(0)
259 :
260 : //creates a new static variable inside the function called <name>setshader
261 : //then sets to it any(if present) args passed to set to the shader
262 : //can only be called once per function, and not in the global scope
263 : //upon calling set(), the shader associated with the name is loaded into OpenGL
264 : #define SETSHADER(name, ...) \
265 : do { \
266 : static Shader *name##shader = nullptr; \
267 : if(!name##shader) \
268 : { \
269 : name##shader = lookupshaderbyname(#name); \
270 : } \
271 : if(name##shader) \
272 : { \
273 : name##shader->set(__VA_ARGS__); \
274 : } \
275 : } while(0)
276 : #define SETVARIANT(name, ...) \
277 : do { \
278 : static Shader *name##shader = nullptr; \
279 : if(!name##shader) name##shader = lookupshaderbyname(#name); \
280 : name##shader->setvariant(__VA_ARGS__); \
281 : } while(0)
282 :
283 : #endif
|