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