goat3dgfx
view src/unistate.cc @ 33:253542d715f4
default texture
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 02 Mar 2014 06:32:37 +0200 |
parents | 1873dfd13f2d |
children |
line source
1 #include <map>
2 #include <vector>
3 #include "unistate.h"
4 #include "shader.h"
5 #include "logger.h"
7 using namespace goatgfx;
9 struct StateItem {
10 StType type;
12 union {
13 int ival[4];
14 float fval[16];
15 };
16 int transpose; // for matrices
17 };
19 static const char *typestr(StType type);
20 static int type_nelem(StType type);
21 static StType float_type(int elem);
22 static StType int_type(int elem);
24 namespace goatgfx {
26 std::vector<StateItem> state;
27 std::map<std::string, int> stateidx;
30 int add_unistate(const char *name, StType type)
31 {
32 static const float ident3[] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
33 static const float ident4[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
35 if(stateidx.find(name) != stateidx.end()) {
36 return stateidx[name];
37 }
39 StateItem sitem;
40 memset(&sitem, 0, sizeof sitem);
41 sitem.type = type;
43 // initialize to a reasonable default value
44 switch(type) {
45 case ST_MATRIX3:
46 memcpy(sitem.fval, ident3, sizeof ident3);
47 break;
49 case ST_MATRIX4:
50 memcpy(sitem.fval, ident4, sizeof ident4);
51 break;
53 default:
54 break; // in all other cases leave it zero (see memset above)
55 }
57 int sidx = state.size();
58 state.push_back(sitem);
59 stateidx[name] = sidx;
61 debug_log("adding uniform state [%d]: %s %s\n", sidx, typestr(sitem.type), name);
63 return sidx;
64 }
66 int get_unistate_index(const char *name)
67 {
68 std::map<std::string, int>::const_iterator it = stateidx.find(name);
69 if(it != stateidx.end()) {
70 return it->second;
71 }
72 return -1;
73 }
75 #define CHECK_INDEX(i) \
76 if(i < 0 || i >= (int)state.size()) return
78 #define CHECK_COUNT(count, type) \
79 do { \
80 int max_elem = type_nelem(type); \
81 if(!(count) || (count) > max_elem) { \
82 count = max_elem; \
83 } \
84 } while(0)
86 void set_unistate(int sidx, const int *val, int count)
87 {
88 CHECK_INDEX(sidx);
89 CHECK_COUNT(count, state[sidx].type);
91 memcpy(state[sidx].ival, val, count * sizeof *state[sidx].ival);
92 }
94 void set_unistate(int sidx, const float *val, int count)
95 {
96 CHECK_INDEX(sidx);
97 CHECK_COUNT(count, state[sidx].type);
99 memcpy(state[sidx].fval, val, count * sizeof *state[sidx].fval);
100 state[sidx].transpose = 0;
101 }
103 void get_unistate(int sidx, int *val, int count)
104 {
105 CHECK_INDEX(sidx);
106 CHECK_COUNT(count, state[sidx].type);
108 memcpy(val, state[sidx].ival, count * sizeof *val);
109 }
111 void get_unistate(int sidx, float *val, int count)
112 {
113 CHECK_INDEX(sidx);
114 CHECK_COUNT(count, state[sidx].type);
116 memcpy(val, state[sidx].fval, count * sizeof *val);
117 }
119 void set_unistate(int sidx, int val)
120 {
121 set_unistate(sidx, &val, 1);
122 }
124 void set_unistate(int sidx, float val)
125 {
126 set_unistate(sidx, &val, 1);
127 }
129 void set_unistate(int sidx, const Vector2 &vec)
130 {
131 set_unistate(sidx, &vec.x, 2);
132 }
134 void set_unistate(int sidx, const Vector3 &vec)
135 {
136 set_unistate(sidx, &vec.x, 3);
137 }
139 void set_unistate(int sidx, const Vector4 &vec)
140 {
141 set_unistate(sidx, &vec.x, 4);
142 }
144 void set_unistate(int sidx, const Matrix3x3 &mat)
145 {
146 set_unistate(sidx, mat[0], 9);
147 state[sidx].transpose = 1;
148 }
150 void set_unistate(int sidx, const Matrix4x4 &mat)
151 {
152 set_unistate(sidx, mat[0], 16);
153 state[sidx].transpose = 1;
154 }
157 int set_unistate(const char *name, int *val, int count)
158 {
159 int sidx = get_unistate_index(name);
160 if(sidx < 0) {
161 StType type = int_type(count);
162 if(type == ST_UNKNOWN) {
163 error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
164 count, name);
165 return -1;
166 }
168 sidx = add_unistate(name, type);
169 }
170 set_unistate(sidx, val);
171 return sidx;
172 }
174 int set_unistate(const char *name, float *val, int count)
175 {
176 int sidx = get_unistate_index(name);
177 if(sidx < 0) {
178 StType type = float_type(count);
179 if(type == ST_UNKNOWN) {
180 error_log("invalid element count (%d) while setting previously unknown unistate item \"%s\"\n",
181 count, name);
182 return -1;
183 }
185 sidx = add_unistate(name, type);
186 }
187 set_unistate(sidx, val);
188 return sidx;
189 }
191 int set_unistate(const char *name, int val)
192 {
193 int sidx = get_unistate_index(name);
194 if(sidx < 0) {
195 sidx = add_unistate(name, ST_INT);
196 }
197 set_unistate(sidx, val);
198 return sidx;
199 }
201 int set_unistate(const char *name, float val)
202 {
203 int sidx = get_unistate_index(name);
204 if(sidx < 0) {
205 sidx = add_unistate(name, ST_FLOAT);
206 }
207 set_unistate(sidx, val);
208 return sidx;
209 }
211 int set_unistate(const char *name, const Vector2 &vec)
212 {
213 int sidx = get_unistate_index(name);
214 if(sidx < 0) {
215 sidx = add_unistate(name, ST_FLOAT2);
216 }
217 set_unistate(sidx, vec);
218 return sidx;
219 }
221 int set_unistate(const char *name, const Vector3 &vec)
222 {
223 int sidx = get_unistate_index(name);
224 if(sidx < 0) {
225 sidx = add_unistate(name, ST_FLOAT3);
226 }
227 set_unistate(sidx, vec);
228 return sidx;
229 }
231 int set_unistate(const char *name, const Vector4 &vec)
232 {
233 int sidx = get_unistate_index(name);
234 if(sidx < 0) {
235 sidx = add_unistate(name, ST_FLOAT4);
236 }
237 set_unistate(sidx, vec);
238 return sidx;
239 }
241 int set_unistate(const char *name, const Matrix3x3 &mat)
242 {
243 int sidx = get_unistate_index(name);
244 if(sidx < 0) {
245 sidx = add_unistate(name, ST_MATRIX3);
246 }
247 set_unistate(sidx, mat);
248 return sidx;
249 }
251 int set_unistate(const char *name, const Matrix4x4 &mat)
252 {
253 int sidx = get_unistate_index(name);
254 if(sidx < 0) {
255 sidx = add_unistate(name, ST_MATRIX4);
256 }
257 set_unistate(sidx, mat);
258 return sidx;
259 }
262 int get_unistate_int(int sidx)
263 {
264 int val = 0;
265 get_unistate(sidx, &val, 1);
266 return val;
267 }
269 float get_unistate_float(int sidx)
270 {
271 float val = 0.0f;
272 get_unistate(sidx, &val, 1);
273 return val;
274 }
276 Vector2 get_unistate_vec2(int sidx)
277 {
278 float val[2] = {0.0f, 0.0f};
279 get_unistate(sidx, val, 2);
280 return Vector2(val[0], val[1]);
281 }
283 Vector3 get_unistate_vec3(int sidx)
284 {
285 float val[3] = {0.0f, 0.0f, 0.0f};
286 get_unistate(sidx, val, 3);
287 return Vector3(val[0], val[1], val[2]);
288 }
290 Vector4 get_unistate_vec4(int sidx)
291 {
292 float val[4] = {0.0f, 0.0f, 0.0f};
293 get_unistate(sidx, val, 4);
294 return Vector4(val[0], val[1], val[2], val[3]);
295 }
297 Matrix3x3 get_unistate_mat3(int sidx)
298 {
299 Matrix3x3 res;
300 get_unistate(sidx, res.m[0], 9);
301 return res;
302 }
304 Matrix4x4 get_unistate_mat4(int sidx)
305 {
306 Matrix4x4 res;
307 get_unistate(sidx, res.m[0], 16);
308 return res;
309 }
312 int get_unistate_int(const char *name)
313 {
314 int sidx = get_unistate_index(name);
315 if(sidx == -1) {
316 return 0;
317 }
318 return get_unistate_int(sidx);
319 }
321 float get_unistate_float(const char *name)
322 {
323 int sidx = get_unistate_index(name);
324 if(sidx == -1) {
325 return 0.0f;
326 }
327 return get_unistate_float(sidx);
328 }
330 Vector2 get_unistate_vec2(const char *name)
331 {
332 int sidx = get_unistate_index(name);
333 if(sidx == -1) {
334 return Vector2();
335 }
336 return get_unistate_vec2(sidx);
337 }
339 Vector3 get_unistate_vec3(const char *name)
340 {
341 int sidx = get_unistate_index(name);
342 if(sidx == -1) {
343 return Vector3();
344 }
345 return get_unistate_vec3(sidx);
346 }
348 Vector4 get_unistate_vec4(const char *name)
349 {
350 int sidx = get_unistate_index(name);
351 if(sidx == -1) {
352 return Vector4();
353 }
354 return get_unistate_vec4(sidx);
355 }
357 Matrix3x3 get_unistate_mat3(const char *name)
358 {
359 int sidx = get_unistate_index(name);
360 if(sidx == -1) {
361 return Matrix3x3();
362 }
363 return get_unistate_mat3(sidx);
364 }
366 Matrix4x4 get_unistate_mat4(const char *name)
367 {
368 int sidx = get_unistate_index(name);
369 if(sidx == -1) {
370 return Matrix4x4();
371 }
372 return get_unistate_mat4(sidx);
373 }
376 void setup_unistate(const ShaderProg *sdr)
377 {
378 if(!sdr) {
379 if(!(sdr = ShaderProg::current)) {
380 return;
381 }
382 }
384 sdr->setup_state_uniforms();
385 }
387 bool setup_unistate(int sidx, const ShaderProg *sdr, int loc)
388 {
389 if(loc < 0 || sidx < 0 || sidx >= (int)state.size()) {
390 return false;
391 }
393 CHECKGLERR;
394 glUseProgram(sdr->get_id());
395 CHECKGLERR;
397 switch(state[sidx].type) {
398 case ST_INT:
399 glUniform1iv(loc, 1, state[sidx].ival);
400 break;
401 case ST_INT2:
402 glUniform2iv(loc, 1, state[sidx].ival);
403 break;
404 case ST_INT3:
405 glUniform3iv(loc, 1, state[sidx].ival);
406 break;
407 case ST_INT4:
408 glUniform4iv(loc, 1, state[sidx].ival);
409 break;
411 case ST_FLOAT:
412 glUniform1fv(loc, 1, state[sidx].fval);
413 break;
414 case ST_FLOAT2:
415 glUniform2fv(loc, 1, state[sidx].fval);
416 break;
417 case ST_FLOAT3:
418 glUniform3fv(loc, 1, state[sidx].fval);
419 break;
420 case ST_FLOAT4:
421 glUniform4fv(loc, 1, state[sidx].fval);
422 break;
424 case ST_MATRIX3:
425 #ifdef GL_ES_VERSION_2_0
426 {
427 float tmat[9], *ptr = tmat;
428 for(int i=0; i<3; i++) {
429 for(int j=0; j<3; j++) {
430 *ptr++ = state[sidx].fval[j * 3 + i];
431 }
432 }
433 glUniformMatrix3fv(loc, 1, GL_FALSE, tmat);
434 }
435 #else
436 glUniformMatrix3fv(loc, 1, state[sidx].transpose, state[sidx].fval);
437 #endif
438 break;
440 case ST_MATRIX4:
441 #ifdef GL_ES_VERSION_2_0
442 {
443 float tmat[16], *ptr = tmat;
444 for(int i=0; i<4; i++) {
445 for(int j=0; j<4; j++) {
446 *ptr++ = state[sidx].fval[j * 4 + i];
447 }
448 }
449 glUniformMatrix4fv(loc, 1, GL_FALSE, tmat);
450 }
451 #else
452 glUniformMatrix4fv(loc, 1, state[sidx].transpose, state[sidx].fval);
453 #endif
454 break;
456 default:
457 return false;
458 }
460 CHECKGLERR;
461 return true;
462 }
464 bool setup_unistate(const char *name, const ShaderProg *sdr)
465 {
466 int loc = sdr->get_uniform_location(name);
467 if(loc == -1) {
468 return false;
469 }
470 return setup_unistate(get_unistate_index(name), sdr, loc);
471 }
473 void set_world_matrix(const Matrix4x4 &mat)
474 {
475 static int sidx = -1, sidx_transp, sidx_mat3;
477 if(sidx == -1) {
478 sidx = add_unistate("st_world_matrix", ST_MATRIX4);
479 sidx_mat3 = add_unistate("st_world_matrix3", ST_MATRIX3);
480 sidx_transp = add_unistate("st_world_matrix_transpose", ST_MATRIX4);
481 }
483 set_unistate(sidx, mat);
484 set_unistate(sidx_mat3, Matrix3x3(mat));
485 set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag
486 }
488 void set_view_matrix(const Matrix4x4 &mat)
489 {
490 static int sidx = -1, sidx_transp, sidx_mat3;
492 if(sidx == -1) {
493 sidx = add_unistate("st_view_matrix", ST_MATRIX4);
494 sidx_mat3 = add_unistate("st_view_matrix3", ST_MATRIX3);
495 sidx_transp = add_unistate("st_view_matrix_transpose", ST_MATRIX4);
496 }
498 set_unistate(sidx, mat);
499 set_unistate(sidx_mat3, Matrix3x3(mat));
500 set_unistate(sidx_transp, mat[0]); // by using the float* variant, we unset the transpose flag
501 }
503 void set_projection_matrix(const Matrix4x4 &mat)
504 {
505 static int sidx = -1;
507 if(sidx == -1) {
508 sidx = add_unistate("st_proj_matrix", ST_MATRIX4);
509 }
511 set_unistate(sidx, mat);
512 }
514 void set_texture_matrix(const Matrix4x4 &mat)
515 {
516 static int sidx = -1;
518 if(sidx == -1) {
519 sidx = add_unistate("st_tex_matrix", ST_MATRIX4);
520 }
522 set_unistate(sidx, mat);
523 }
525 Matrix4x4 get_world_matrix()
526 {
527 static int sidx = -1;
529 if(sidx == -1) {
530 if((sidx = get_unistate_index("st_world_matrix")) == -1) {
531 return Matrix4x4();
532 }
533 }
534 return get_unistate_mat4(sidx);
535 }
537 Matrix4x4 get_view_matrix()
538 {
539 static int sidx = -1;
541 if(sidx == -1) {
542 if((sidx = get_unistate_index("st_view_matrix")) == -1) {
543 return Matrix4x4();
544 }
545 }
546 return get_unistate_mat4(sidx);
547 }
549 Matrix4x4 get_projection_matrix()
550 {
551 static int sidx = -1;
553 if(sidx == -1) {
554 if((sidx = get_unistate_index("st_proj_matrix")) == -1) {
555 return Matrix4x4();
556 }
557 }
558 return get_unistate_mat4(sidx);
559 }
561 Matrix4x4 get_texture_matrix()
562 {
563 static int sidx = -1;
565 if(sidx == -1) {
566 if((sidx = get_unistate_index("st_tex_matrix")) == -1) {
567 return Matrix4x4();
568 }
569 }
570 return get_unistate_mat4(sidx);
571 }
573 void setup_gl_matrices()
574 {
575 #ifdef USE_OLDGL
576 Matrix4x4 modelview = get_world_matrix() * get_view_matrix();
577 Matrix4x4 proj = get_projection_matrix();
578 Matrix4x4 tex = get_texture_matrix();
580 glMatrixMode(GL_TEXTURE);
581 glLoadTransposeMatrixf(tex[0]);
582 glMatrixMode(GL_PROJECTION);
583 glLoadTransposeMatrixf(proj[0]);
584 glMatrixMode(GL_MODELVIEW);
585 glLoadTransposeMatrixf(modelview[0]);
586 #endif
587 }
589 } // namespace goatgfx
591 static const char *typestr(StType type)
592 {
593 switch(type) {
594 case ST_INT:
595 return "int";
596 case ST_INT2:
597 return "ivec2";
598 case ST_INT3:
599 return "ivec3";
600 case ST_INT4:
601 return "ivec4";
602 case ST_FLOAT:
603 return "float";
604 case ST_FLOAT2:
605 return "vec2";
606 case ST_FLOAT3:
607 return "vec3";
608 case ST_FLOAT4:
609 return "vec4";
610 case ST_MATRIX3:
611 return "mat3";
612 case ST_MATRIX4:
613 return "mat4";
615 default:
616 break;
617 }
618 return "<unknown>";
619 }
621 static int type_nelem(StType type)
622 {
623 switch(type) {
624 case ST_INT:
625 case ST_FLOAT:
626 return 1;
627 case ST_INT2:
628 case ST_FLOAT2:
629 return 2;
630 case ST_INT3:
631 case ST_FLOAT3:
632 return 3;
633 case ST_INT4:
634 case ST_FLOAT4:
635 return 4;
636 case ST_MATRIX3:
637 return 9;
638 case ST_MATRIX4:
639 return 16;
641 default:
642 break;
643 }
645 return 0;
646 }
648 static StType float_type(int elem)
649 {
650 switch(elem) {
651 case 1:
652 return ST_FLOAT;
653 case 2:
654 return ST_FLOAT2;
655 case 3:
656 return ST_FLOAT3;
657 case 4:
658 return ST_FLOAT4;
659 case 9:
660 return ST_MATRIX3;
661 case 16:
662 return ST_MATRIX4;
663 default:
664 break;
665 }
666 return ST_UNKNOWN;
667 }
669 static StType int_type(int elem)
670 {
671 switch(elem) {
672 case 1:
673 return ST_INT;
674 case 2:
675 return ST_INT2;
676 case 3:
677 return ST_INT3;
678 case 4:
679 return ST_INT4;
680 default:
681 break;
682 }
683 return ST_UNKNOWN;
684 }