14 int transpose; // for matrices
17 static const char *typestr(StType type);
18 static int type_nelem(StType type);
19 static StType float_type(int elem);
20 static StType int_type(int elem);
22 std::vector<StateItem> state;
23 std::map<std::string, int> stateidx;
26 int add_unistate(const char *name, StType type)
28 static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
29 static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
31 if(stateidx.find(name) != stateidx.end()) {
32 return stateidx[name];
36 memset(&sitem, 0, sizeof sitem);
39 // initialize to a reasonable default value
42 memcpy(sitem.fval, ident3, sizeof ident3);
46 memcpy(sitem.fval, ident4, sizeof ident4);
50 break; // in all other cases leave it zero (see memset above)
53 int sidx = state.size();
54 state.push_back(sitem);
55 stateidx[name] = sidx;
57 debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name);
62 int get_unistate_index(const char *name)
64 std::map<std::string, int>::const_iterator it = stateidx.find(name);
65 if(it != stateidx.end()) {
71 #define CHECK_INDEX(i) \
72 if(i < 0 || i >= (int)state.size()) return
74 #define CHECK_COUNT(count, type) \
76 int max_elem = type_nelem(type); \
77 if(!(count) || (count) > max_elem) { \
82 void set_unistate(int sidx, const int *val, int count)
85 CHECK_COUNT(count, state[sidx].type);
87 memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival);
90 void set_unistate(int sidx, const float *val, int count)
93 CHECK_COUNT(count, state[sidx].type);
95 memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval);
96 state[sidx].transpose = 0;
99 void get_unistate(int sidx, int *val, int count)
102 CHECK_COUNT(count, state[sidx].type);
104 memcpy(val, state[sidx].ival, count * sizeof *val);
107 void get_unistate(int sidx, float *val, int count)
110 CHECK_COUNT(count, state[sidx].type);
112 memcpy(val, state[sidx].fval, count * sizeof *val);
115 void set_unistate(int sidx, int val)
117 set_unistate(sidx, &val, 1);
120 void set_unistate(int sidx, float val)
122 set_unistate(sidx, &val, 1);
125 void set_unistate(int sidx, const Vec2 &vec)
127 set_unistate(sidx, &vec.x, 2);
130 void set_unistate(int sidx, const Vec3 &vec)
132 set_unistate(sidx, &vec.x, 3);
135 void set_unistate(int sidx, const Vec4 &vec)
137 set_unistate(sidx, &vec.x, 4);
140 void set_unistate(int sidx, const Mat3 &mat)
142 set_unistate(sidx, mat[0], 9);
143 state[sidx].transpose = 0;
146 void set_unistate(int sidx, const Mat4 &mat)
148 set_unistate(sidx, mat[0], 16);
149 state[sidx].transpose = 0;
153 int set_unistate(const char *name, int *val, int count)
155 int sidx = get_unistate_index(name);
157 StType type = int_type(count);
158 if(type == ST_UNKNOWN) {
159 error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
164 sidx = add_unistate(name, type);
166 set_unistate(sidx, val);
170 int set_unistate(const char *name, float *val, int count)
172 int sidx = get_unistate_index(name);
174 StType type = float_type(count);
175 if(type == ST_UNKNOWN) {
176 error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
181 sidx = add_unistate(name, type);
183 set_unistate(sidx, val);
187 int set_unistate(const char *name, int val)
189 int sidx = get_unistate_index(name);
191 sidx = add_unistate(name, ST_INT);
193 set_unistate(sidx, val);
197 int set_unistate(const char *name, float val)
199 int sidx = get_unistate_index(name);
201 sidx = add_unistate(name, ST_FLOAT);
203 set_unistate(sidx, val);
207 int set_unistate(const char *name, const Vec2 &vec)
209 int sidx = get_unistate_index(name);
211 sidx = add_unistate(name, ST_FLOAT2);
213 set_unistate(sidx, vec);
217 int set_unistate(const char *name, const Vec3 &vec)
219 int sidx = get_unistate_index(name);
221 sidx = add_unistate(name, ST_FLOAT3);
223 set_unistate(sidx, vec);
227 int set_unistate(const char *name, const Vec4 &vec)
229 int sidx = get_unistate_index(name);
231 sidx = add_unistate(name, ST_FLOAT4);
233 set_unistate(sidx, vec);
237 int set_unistate(const char *name, const Mat3 &mat)
239 int sidx = get_unistate_index(name);
241 sidx = add_unistate(name, ST_MATRIX3);
243 set_unistate(sidx, mat);
247 int set_unistate(const char *name, const Mat4 &mat)
249 int sidx = get_unistate_index(name);
251 sidx = add_unistate(name, ST_MATRIX4);
253 set_unistate(sidx, mat);
258 int get_unistate_int(int sidx)
261 get_unistate(sidx, &val, 1);
265 float get_unistate_float(int sidx)
268 get_unistate(sidx, &val, 1);
272 Vec2 get_unistate_vec2(int sidx)
274 float val[2] = {0.0f, 0.0f};
275 get_unistate(sidx, val, 2);
276 return Vec2(val[0], val[1]);
279 Vec3 get_unistate_vec3(int sidx)
281 float val[3] = {0.0f, 0.0f, 0.0f};
282 get_unistate(sidx, val, 3);
283 return Vec3(val[0], val[1], val[2]);
286 Vec4 get_unistate_vec4(int sidx)
288 float val[4] = {0.0f, 0.0f, 0.0f};
289 get_unistate(sidx, val, 4);
290 return Vec4(val[0], val[1], val[2], val[3]);
293 Mat3 get_unistate_mat3(int sidx)
296 get_unistate(sidx, res.m[0], 9);
300 Mat4 get_unistate_mat4(int sidx)
303 get_unistate(sidx, res.m[0], 16);
308 int get_unistate_int(const char *name)
310 int sidx = get_unistate_index(name);
314 return get_unistate_int(sidx);
317 float get_unistate_float(const char *name)
319 int sidx = get_unistate_index(name);
323 return get_unistate_float(sidx);
326 Vec2 get_unistate_vec2(const char *name)
328 int sidx = get_unistate_index(name);
332 return get_unistate_vec2(sidx);
335 Vec3 get_unistate_vec3(const char *name)
337 int sidx = get_unistate_index(name);
341 return get_unistate_vec3(sidx);
344 Vec4 get_unistate_vec4(const char *name)
346 int sidx = get_unistate_index(name);
350 return get_unistate_vec4(sidx);
353 Mat3 get_unistate_mat3(const char *name)
355 int sidx = get_unistate_index(name);
359 return get_unistate_mat3(sidx);
362 Mat4 get_unistate_mat4(const char *name)
364 int sidx = get_unistate_index(name);
368 return get_unistate_mat4(sidx);
372 void setup_unistate(const ShaderProg *sdr)
375 if(!(sdr = ShaderProg::current)) {
380 sdr->setup_state_uniforms();
383 bool setup_unistate(int sidx, const ShaderProg *sdr, int loc)
385 if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) {
389 glUseProgram(sdr->get_id());
391 switch(state[sidx].type) {
393 glUniform1iv(loc, 1, state[sidx].ival);
396 glUniform2iv(loc, 1, state[sidx].ival);
399 glUniform3iv(loc, 1, state[sidx].ival);
402 glUniform4iv(loc, 1, state[sidx].ival);
406 glUniform1fv(loc, 1, state[sidx].fval);
409 glUniform2fv(loc, 1, state[sidx].fval);
412 glUniform3fv(loc, 1, state[sidx].fval);
415 glUniform4fv(loc, 1, state[sidx].fval);
419 #ifdef GL_ES_VERSION_2_0
421 float tmat[9], *ptr = tmat;
422 for(int i=0; i<3; i++) {
423 for(int j=0; j<3; j++) {
424 *ptr++ = state[sidx].fval[j * 3 + i];
427 glUniformMatrix3fv(loc, 1, GL_FALSE, tmat);
430 glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval);
435 #ifdef GL_ES_VERSION_2_0
437 float tmat[16], *ptr = tmat;
438 for(int i=0; i<4; i++) {
439 for(int j=0; j<4; j++) {
440 *ptr++ = state[sidx].fval[j * 4 + i];
443 glUniformMatrix4fv(loc, 1, GL_FALSE, tmat);
446 glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval);
457 bool setup_unistate(const char *name, const ShaderProg *sdr)
459 int loc = sdr->get_uniform_location(name);
463 return setup_unistate(get_unistate_index(name), sdr, loc);
466 void set_world_matrix(const Mat4 &mat)
468 static int sidx = -1, sidx_transp, sidx_mat3;
471 sidx = add_unistate("st_world_matrix", ST_MATRIX4);
472 sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3);
473 sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4);
476 set_unistate(sidx, mat);
477 set_unistate(sidx_mat3, mat.submatrix(3, 3));
478 set_unistate(sidx_transp, mat[0]);
479 state[sidx_transp].transpose = 1;
482 void set_view_matrix(const Mat4 &mat)
484 static int sidx = -1, sidx_transp, sidx_mat3;
487 sidx = add_unistate("st_view_matrix", ST_MATRIX4);
488 sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3);
489 sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4);
492 set_unistate(sidx, mat);
493 set_unistate(sidx_mat3, mat.submatrix(3, 3));
494 set_unistate(sidx_transp, mat[0]);
495 state[sidx_transp].transpose = 1;
498 void set_projection_matrix(const Mat4 &mat)
500 static int sidx = -1;
503 sidx = add_unistate("st_proj_matrix", ST_MATRIX4);
506 set_unistate(sidx, mat);
509 void set_texture_matrix(const Mat4 &mat)
511 static int sidx = -1;
514 sidx = add_unistate("st_tex_matrix", ST_MATRIX4);
517 set_unistate(sidx, mat);
520 Mat4 get_world_matrix()
522 static int sidx = -1;
525 if((sidx = get_unistate_index("st_world_matrix")) == -1) {
529 return get_unistate_mat4(sidx);
532 Mat4 get_view_matrix()
534 static int sidx = -1;
537 if((sidx = get_unistate_index("st_view_matrix")) == -1) {
541 return get_unistate_mat4(sidx);
544 Mat4 get_projection_matrix()
546 static int sidx = -1;
549 if((sidx = get_unistate_index("st_proj_matrix")) == -1) {
553 return get_unistate_mat4(sidx);
556 Mat4 get_texture_matrix()
558 static int sidx = -1;
561 if((sidx = get_unistate_index("st_tex_matrix")) == -1) {
565 return get_unistate_mat4(sidx);
568 void setup_gl_matrices()
571 Mat4 modelview = get_view_matrix() * get_world_matrix();
572 Mat4 proj = get_projection_matrix();
573 Mat4 tex = get_texture_matrix();
575 glMatrixMode(GL_TEXTURE);
576 glLoadTransposeMatrixf(tex[0]);
577 glMatrixMode(GL_PROJECTION);
578 glLoadTransposeMatrixf(proj[0]);
579 glMatrixMode(GL_MODELVIEW);
580 glLoadTransposeMatrixf(modelview[0]);
584 static const char *typestr(StType type)
614 static int type_nelem(StType type)
641 static StType float_type(int elem)
662 static StType int_type(int elem)