goat3dgfx
view src/unistate.cc @ 13:25bf39105c82
lalal
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 27 Nov 2013 08:08:59 +0200 |
parents | |
children | 7d6b667821cf |
line source
1 #include <map>
2 #include <vector>
3 #include "unistate.h"
4 #include "shader.h"
5 #include "logger.h"
7 struct StateItem {
8 StType type;
10 union {
11 int ival[4];
12 float fval[16];
13 };
14 int transpose; // for matrices
15 };
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)
27 {
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];
33 }
35 StateItem sitem;
36 memset(&sitem, 0, sizeof sitem);
37 sitem.type = type;
39 // initialize to a reasonable default value
40 switch(type) {
41 case ST_MATRIX3:
42 memcpy(sitem.fval, ident3, sizeof ident3);
43 break;
45 case ST_MATRIX4:
46 memcpy(sitem.fval, ident4, sizeof ident4);
47 break;
49 default:
50 break; // in all other cases leave it zero (see memset above)
51 }
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);
59 return sidx;
60 }
62 int get_unistate_index(const char *name)
63 {
64 std::map<std::string, int>::const_iterator it = stateidx.find(name);
65 if(it != stateidx.end()) {
66 return it->second;
67 }
68 return -1;
69 }
71 #define CHECK_INDEX(i) \
72 if(i < 0 || i >= (int)state.size()) return
74 #define CHECK_COUNT(count, type) \
75 do { \
76 int max_elem = type_nelem(type); \
77 if(!(count) || (count) > max_elem) { \
78 count = max_elem; \
79 } \
80 } while(0)
82 void set_unistate(int sidx, const int *val, int count)
83 {
84 CHECK_INDEX(sidx);
85 CHECK_COUNT(count, state[sidx].type);
87 memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival);
88 }
90 void set_unistate(int sidx, const float *val, int count)
91 {
92 CHECK_INDEX(sidx);
93 CHECK_COUNT(count, state[sidx].type);
95 memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval);
96 state[sidx].transpose = 0;
97 }
99 void get_unistate(int sidx, int *val, int count)
100 {
101 CHECK_INDEX(sidx);
102 CHECK_COUNT(count, state[sidx].type);
104 memcpy(val, state[sidx].ival, count * sizeof *val);
105 }
107 void get_unistate(int sidx, float *val, int count)
108 {
109 CHECK_INDEX(sidx);
110 CHECK_COUNT(count, state[sidx].type);
112 memcpy(val, state[sidx].fval, count * sizeof *val);
113 }
115 void set_unistate(int sidx, int val)
116 {
117 set_unistate(sidx, &val, 1);
118 }
120 void set_unistate(int sidx, float val)
121 {
122 set_unistate(sidx, &val, 1);
123 }
125 void set_unistate(int sidx, const Vector2 &vec)
126 {
127 set_unistate(sidx, &vec.x, 2);
128 }
130 void set_unistate(int sidx, const Vector3 &vec)
131 {
132 set_unistate(sidx, &vec.x, 3);
133 }
135 void set_unistate(int sidx, const Vector4 &vec)
136 {
137 set_unistate(sidx, &vec.x, 4);
138 }
140 void set_unistate(int sidx, const Matrix3x3 &mat)
141 {
142 set_unistate(sidx, mat[0], 9);
143 state[sidx].transpose = 1;
144 }
146 void set_unistate(int sidx, const Matrix4x4 &mat)
147 {
148 set_unistate(sidx, mat[0], 16);
149 state[sidx].transpose = 1;
150 }
153 int set_unistate(const char *name, int *val, int count)
154 {
155 int sidx = get_unistate_index(name);
156 if(sidx < 0) {
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",
160 count, name);
161 return -1;
162 }
164 sidx = add_unistate(name, type);
165 }
166 set_unistate(sidx, val);
167 return sidx;
168 }
170 int set_unistate(const char *name, float *val, int count)
171 {
172 int sidx = get_unistate_index(name);
173 if(sidx < 0) {
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",
177 count, name);
178 return -1;
179 }
181 sidx = add_unistate(name, type);
182 }
183 set_unistate(sidx, val);
184 return sidx;
185 }
187 int set_unistate(const char *name, int val)
188 {
189 int sidx = get_unistate_index(name);
190 if(sidx < 0) {
191 sidx = add_unistate(name, ST_INT);
192 }
193 set_unistate(sidx, val);
194 return sidx;
195 }
197 int set_unistate(const char *name, float val)
198 {
199 int sidx = get_unistate_index(name);
200 if(sidx < 0) {
201 sidx = add_unistate(name, ST_FLOAT);
202 }
203 set_unistate(sidx, val);
204 return sidx;
205 }
207 int set_unistate(const char *name, const Vector2 &vec)
208 {
209 int sidx = get_unistate_index(name);
210 if(sidx < 0) {
211 sidx = add_unistate(name, ST_FLOAT2);
212 }
213 set_unistate(sidx, vec);
214 return sidx;
215 }
217 int set_unistate(const char *name, const Vector3 &vec)
218 {
219 int sidx = get_unistate_index(name);
220 if(sidx < 0) {
221 sidx = add_unistate(name, ST_FLOAT3);
222 }
223 set_unistate(sidx, vec);
224 return sidx;
225 }
227 int set_unistate(const char *name, const Vector4 &vec)
228 {
229 int sidx = get_unistate_index(name);
230 if(sidx < 0) {
231 sidx = add_unistate(name, ST_FLOAT4);
232 }
233 set_unistate(sidx, vec);
234 return sidx;
235 }
237 int set_unistate(const char *name, const Matrix3x3 &mat)
238 {
239 int sidx = get_unistate_index(name);
240 if(sidx < 0) {
241 sidx = add_unistate(name, ST_MATRIX3);
242 }
243 set_unistate(sidx, mat);
244 return sidx;
245 }
247 int set_unistate(const char *name, const Matrix4x4 &mat)
248 {
249 int sidx = get_unistate_index(name);
250 if(sidx < 0) {
251 sidx = add_unistate(name, ST_MATRIX4);
252 }
253 set_unistate(sidx, mat);
254 return sidx;
255 }
258 int get_unistate_int(int sidx)
259 {
260 int val = 0;
261 get_unistate(sidx, &val, 1);
262 return val;
263 }
265 float get_unistate_float(int sidx)
266 {
267 float val = 0.0f;
268 get_unistate(sidx, &val, 1);
269 return val;
270 }
272 Vector2 get_unistate_vec2(int sidx)
273 {
274 float val[2] = {0.0f, 0.0f};
275 get_unistate(sidx, val, 2);
276 return Vector2(val[0], val[1]);
277 }
279 Vector3 get_unistate_vec3(int sidx)
280 {
281 float val[3] = {0.0f, 0.0f, 0.0f};
282 get_unistate(sidx, val, 3);
283 return Vector3(val[0], val[1], val[2]);
284 }
286 Vector4 get_unistate_vec4(int sidx)
287 {
288 float val[4] = {0.0f, 0.0f, 0.0f};
289 get_unistate(sidx, val, 4);
290 return Vector4(val[0], val[1], val[2], val[3]);
291 }
293 Matrix3x3 get_unistate_mat3(int sidx)
294 {
295 Matrix3x3 res;
296 get_unistate(sidx, res.m[0], 9);
297 return res;
298 }
300 Matrix4x4 get_unistate_mat4(int sidx)
301 {
302 Matrix4x4 res;
303 get_unistate(sidx, res.m[0], 16);
304 return res;
305 }
308 int get_unistate_int(const char *name)
309 {
310 int sidx = get_unistate_index(name);
311 if(sidx == -1) {
312 return 0;
313 }
314 return get_unistate_int(sidx);
315 }
317 float get_unistate_float(const char *name)
318 {
319 int sidx = get_unistate_index(name);
320 if(sidx == -1) {
321 return 0.0f;
322 }
323 return get_unistate_float(sidx);
324 }
326 Vector2 get_unistate_vec2(const char *name)
327 {
328 int sidx = get_unistate_index(name);
329 if(sidx == -1) {
330 return Vector2();
331 }
332 return get_unistate_vec2(sidx);
333 }
335 Vector3 get_unistate_vec3(const char *name)
336 {
337 int sidx = get_unistate_index(name);
338 if(sidx == -1) {
339 return Vector3();
340 }
341 return get_unistate_vec3(sidx);
342 }
344 Vector4 get_unistate_vec4(const char *name)
345 {
346 int sidx = get_unistate_index(name);
347 if(sidx == -1) {
348 return Vector4();
349 }
350 return get_unistate_vec4(sidx);
351 }
353 Matrix3x3 get_unistate_mat3(const char *name)
354 {
355 int sidx = get_unistate_index(name);
356 if(sidx == -1) {
357 return Matrix3x3();
358 }
359 return get_unistate_mat3(sidx);
360 }
362 Matrix4x4 get_unistate_mat4(const char *name)
363 {
364 int sidx = get_unistate_index(name);
365 if(sidx == -1) {
366 return Matrix4x4();
367 }
368 return get_unistate_mat4(sidx);
369 }
372 void setup_unistate(const ShaderProg *sdr)
373 {
374 if(!sdr) {
375 if(!(sdr = ShaderProg::current)) {
376 return;
377 }
378 }
380 sdr->setup_state_uniforms();
381 }
383 bool setup_unistate(int sidx, const ShaderProg *sdr, int loc)
384 {
385 if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) {
386 return false;
387 }
389 CHECKGLERR;
390 glUseProgram(sdr->get_id());
391 CHECKGLERR;
393 switch(state[sidx].type) {
394 case ST_INT:
395 glUniform1iv(loc, 1, state[sidx].ival);
396 break;
397 case ST_INT2:
398 glUniform2iv(loc, 1, state[sidx].ival);
399 break;
400 case ST_INT3:
401 glUniform3iv(loc, 1, state[sidx].ival);
402 break;
403 case ST_INT4:
404 glUniform4iv(loc, 1, state[sidx].ival);
405 break;
407 case ST_FLOAT:
408 glUniform1fv(loc, 1, state[sidx].fval);
409 break;
410 case ST_FLOAT2:
411 glUniform2fv(loc, 1, state[sidx].fval);
412 break;
413 case ST_FLOAT3:
414 glUniform3fv(loc, 1, state[sidx].fval);
415 break;
416 case ST_FLOAT4:
417 glUniform4fv(loc, 1, state[sidx].fval);
418 break;
420 case ST_MATRIX3:
421 #ifdef GL_ES_VERSION_2_0
422 {
423 float tmat[9], *ptr = tmat;
424 for(int i=0; i<3; i++) {
425 for(int j=0; j<3; j++) {
426 *ptr++ = state[sidx].fval[j * 3 + i];
427 }
428 }
429 glUniformMatrix3fv(loc, 1, GL_FALSE, tmat);
430 }
431 #else
432 glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval);
433 #endif
434 break;
436 case ST_MATRIX4:
437 #ifdef GL_ES_VERSION_2_0
438 {
439 float tmat[16], *ptr = tmat;
440 for(int i=0; i<4; i++) {
441 for(int j=0; j<4; j++) {
442 *ptr++ = state[sidx].fval[j * 4 + i];
443 }
444 }
445 glUniformMatrix4fv(loc, 1, GL_FALSE, tmat);
446 }
447 #else
448 glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval);
449 #endif
450 break;
452 default:
453 return false;
454 }
456 CHECKGLERR;
457 return true;
458 }
460 bool setup_unistate(const char *name, const ShaderProg *sdr)
461 {
462 int loc = sdr->get_uniform_location(name);
463 if(loc == -1) {
464 return false;
465 }
466 return setup_unistate(get_unistate_index(name), sdr, loc);
467 }
469 void set_world_matrix(const Matrix4x4 &mat)
470 {
471 static int sidx = -1, sidx_transp, sidx_mat3;
473 if(sidx == -1) {
474 sidx = add_unistate("st_world_matrix", ST_MATRIX4);
475 sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3);
476 sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4);
477 }
479 set_unistate(sidx, mat);
480 set_unistate(sidx_mat3, Matrix3x3(mat));
481 set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag
482 }
484 void set_view_matrix(const Matrix4x4 &mat)
485 {
486 static int sidx = -1, sidx_transp, sidx_mat3;
488 if(sidx == -1) {
489 sidx = add_unistate("st_view_matrix", ST_MATRIX4);
490 sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3);
491 sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4);
492 }
494 set_unistate(sidx, mat);
495 set_unistate(sidx_mat3, Matrix3x3(mat));
496 set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag
497 }
499 void set_projection_matrix(const Matrix4x4 &mat)
500 {
501 static int sidx = -1;
503 if(sidx == -1) {
504 sidx = add_unistate("st_proj_matrix", ST_MATRIX4);
505 }
507 set_unistate(sidx, mat);
508 }
510 void set_texture_matrix(const Matrix4x4 &mat)
511 {
512 static int sidx = -1;
514 if(sidx == -1) {
515 sidx = add_unistate("st_tex_matrix", ST_MATRIX4);
516 }
518 set_unistate(sidx, mat);
519 }
521 Matrix4x4 get_world_matrix()
522 {
523 static int sidx = -1;
525 if(sidx == -1) {
526 if((sidx = get_unistate_index("st_world_matrix")) == -1) {
527 return Matrix4x4();
528 }
529 }
530 return get_unistate_mat4(sidx);
531 }
533 Matrix4x4 get_view_matrix()
534 {
535 static int sidx = -1;
537 if(sidx == -1) {
538 if((sidx = get_unistate_index("st_view_matrix")) == -1) {
539 return Matrix4x4();
540 }
541 }
542 return get_unistate_mat4(sidx);
543 }
545 Matrix4x4 get_projection_matrix()
546 {
547 static int sidx = -1;
549 if(sidx == -1) {
550 if((sidx = get_unistate_index("st_proj_matrix")) == -1) {
551 return Matrix4x4();
552 }
553 }
554 return get_unistate_mat4(sidx);
555 }
557 Matrix4x4 get_texture_matrix()
558 {
559 static int sidx = -1;
561 if(sidx == -1) {
562 if((sidx = get_unistate_index("st_tex_matrix")) == -1) {
563 return Matrix4x4();
564 }
565 }
566 return get_unistate_mat4(sidx);
567 }
569 void setup_gl_matrices()
570 {
571 #ifdef USE_OLDGL
572 Matrix4x4 modelview = get_world_matrix() * get_view_matrix();
573 Matrix4x4 proj = get_projection_matrix();
574 Matrix4x4 tex = get_texture_matrix();
576 glMatrixMode(GL_TEXTURE);
577 glLoadTransposeMatrixf(tex[0]);
578 glMatrixMode(GL_PROJECTION);
579 glLoadTransposeMatrixf(proj[0]);
580 glMatrixMode(GL_MODELVIEW);
581 glLoadTransposeMatrixf(modelview[0]);
582 #endif
583 }
585 static const char *typestr(StType type)
586 {
587 switch(type) {
588 case ST_INT:
589 return "int";
590 case ST_INT2:
591 return "ivec2";
592 case ST_INT3:
593 return "ivec3";
594 case ST_INT4:
595 return "ivec4";
596 case ST_FLOAT:
597 return "float";
598 case ST_FLOAT2:
599 return "vec2";
600 case ST_FLOAT3:
601 return "vec3";
602 case ST_FLOAT4:
603 return "vec4";
604 case ST_MATRIX3:
605 return "mat3";
606 case ST_MATRIX4:
607 return "mat4";
609 default:
610 break;
611 }
612 return "<unknown>";
613 }
615 static int type_nelem(StType type)
616 {
617 switch(type) {
618 case ST_INT:
619 case ST_FLOAT:
620 return 1;
621 case ST_INT2:
622 case ST_FLOAT2:
623 return 2;
624 case ST_INT3:
625 case ST_FLOAT3:
626 return 3;
627 case ST_INT4:
628 case ST_FLOAT4:
629 return 4;
630 case ST_MATRIX3:
631 return 9;
632 case ST_MATRIX4:
633 return 16;
635 default:
636 break;
637 }
639 return 0;
640 }
642 static StType float_type(int elem)
643 {
644 switch(elem) {
645 case 1:
646 return ST_FLOAT;
647 case 2:
648 return ST_FLOAT2;
649 case 3:
650 return ST_FLOAT3;
651 case 4:
652 return ST_FLOAT4;
653 case 9:
654 return ST_MATRIX3;
655 case 16:
656 return ST_MATRIX4;
657 default:
658 break;
659 }
660 return ST_UNKNOWN;
661 }
663 static StType int_type(int elem)
664 {
665 switch(elem) {
666 case 1:
667 return ST_INT;
668 case 2:
669 return ST_INT2;
670 case 3:
671 return ST_INT3;
672 case 4:
673 return ST_INT4;
674 default:
675 break;
676 }
677 return ST_UNKNOWN;
678 }