ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/shader.h
Revision: 1.3
Committed: Sat Oct 23 21:53:06 2004 UTC (19 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +206 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #ifndef SHADER_H
2 #define SHADER_H
3
4 #include <sstream>
5
6 #include "opengl.h"
7 #include "util.h"
8
9 namespace shader {
10
11 using namespace std;
12
13 const int NAMELEN = 32;
14
15 template<class T>
16 struct sl_expr {
17 const T t;
18 sl_expr (const T &t) : t(t) { }
19 void operator ()() const { t (); }
20 };
21
22 template<class A, class B>
23 struct sl_concat2
24 {
25 const A a; const B b;
26 sl_concat2 (const A &a, const B &b) : a(a), b(b) { }
27 void operator ()() const { a (); b (); }
28 };
29
30 template<class A, class B, class C>
31 struct sl_concat3
32 {
33 const A a; const B b; const C c;
34 sl_concat3 (const A &a, const B &b, const C &c) : a(a), b(b), c(c) { }
35 void operator ()() const { a (); b (); c (); }
36 };
37
38 template<class A, class B, class C, class D>
39 struct sl_concat4
40 {
41 const A a; const B b; const C c; const D d;
42 sl_concat4 (const A &a, const B &b, const C &c, const D &d) : a(a), b(b), c(c), d(d) { }
43 void operator ()() const { a (); b (); c (); d(); }
44 };
45
46 class refcounted
47 {
48 template<class type> friend class ref;
49 mutable int refcnt;
50 void refcnt_inc () const { refcnt++; }
51 void refcnt_dec () const { if (!--refcnt) delete this; };
52 public:
53 refcounted () : refcnt(0) { }
54 virtual ~refcounted ();
55 };
56
57 template<class type>
58 struct ref
59 {
60 type *p;
61
62 ref ()
63 {
64 p = new type;
65 p->refcnt_inc ();
66 }
67
68 ref (type &d)
69 {
70 d.refcnt_inc ();
71 p = &d;
72 }
73
74 ref (const ref &r)
75 {
76 r.p->refcnt_inc ();
77 p = r.p;
78 }
79
80 template<class type2>
81 ref (const ref<type2> &r)
82 {
83 r.p->refcnt_inc ();
84 p = r.p;
85 }
86
87 ~ref ()
88 {
89 p->refcnt_dec ();
90 }
91
92 ref &operator =(type &d)
93 {
94 d.refcnt_inc ();
95 p->refcnt_dec ();
96 p = &d;
97 return *this;
98 }
99
100 type *operator ->() const { return p; }
101
102 operator type &() const { return *p; }
103
104 template<class type2>
105 bool operator ==(const ref<type2> b) const
106 {
107 return (void *)p == (void *)b.p;
108 }
109 };
110
111 // ref with auto-construct
112 template<class type>
113 struct auto_ref0 : ref<type>
114 {
115 auto_ref0 () : ref<type> (*new type ()) { }
116 };
117
118 template<class type, typename arg1>
119 struct auto_ref1 : ref<type>
120 {
121 auto_ref1 (arg1 a) : ref<type> (*new type (a)) { }
122 };
123
124 template<class type>
125 struct auto_lvalue_ref0 : ref<type>
126 {
127 auto_lvalue_ref0 () : ref<type> (*new type ()) { }
128 template<typename expr>
129 const auto_lvalue_ref0 &operator =(const expr &e) const;
130 };
131
132 template<class type, typename arg1>
133 struct auto_lvalue_ref1 : ref<type>
134 {
135 auto_lvalue_ref1 (arg1 a) : ref<type> (*new type (a)) { }
136 template<class expr>
137 const auto_lvalue_ref1 &operator =(const expr &e) const;
138 };
139
140 extern const char str_float [];
141 extern const char str_vec2 [];
142 extern const char str_vec3 [];
143 extern const char str_vec4 [];
144 extern const char str_mat2 [];
145 extern const char str_mat3 [];
146 extern const char str_mat4 [];
147
148 extern const char str_sampler_1d [];
149 extern const char str_sampler_1d_shadow [];
150 extern const char str_sampler_2d [];
151 extern const char str_sampler_2d_shadow [];
152 extern const char str_sampler_2d_rect [];
153 extern const char str_sampler_2d_rect_shadow [];
154 extern const char str_sampler_3d [];
155 extern const char str_sampler_3d_rect [];
156 extern const char str_sampler_cube [];
157
158 typedef ref<struct var_i> var;
159 typedef ref<struct uniform_i> uniform;
160
161 struct shader_builder
162 {
163 vector<uniform> refs; // uniform parameters
164 vector<var> temps; // temporary variables
165 vector<var> streams; // varying inputs & outputs
166
167 ostringstream source;
168
169 template<typename type>
170 shader_builder &operator <<(const type &t)
171 {
172 source << t;
173 return *this;
174 }
175 };
176
177 struct fragment_i : refcounted
178 {
179 virtual void build (shader_builder &b) = 0;
180 };
181
182 typedef ref<fragment_i> fragment;
183
184 struct lvalue_i : fragment_i
185 {
186 };
187
188 // a simple predeclared variable with unspecified type
189 struct glvar_i : lvalue_i
190 {
191 const char *name;
192 void build (shader_builder &b);
193 glvar_i (const char *name) : name (name) { }
194 };
195
196 typedef auto_lvalue_ref1<glvar_i, const char *> glvar;
197
198 struct var_i : lvalue_i
199 {
200 static unsigned int next_id;
201
202 char name[NAMELEN];
203 const char *typestr;
204
205 void build (shader_builder &b);
206 virtual void build_decl (ostringstream &b);
207
208 var_i (const char *typestr);
209 ~var_i ();
210 };
211
212 struct uniform_i : var_i
213 {
214 bool dirty;
215
216 virtual void update () = 0;
217
218 void build (shader_builder &b);
219 void build_decl (ostringstream &b);
220 uniform_i (const char *strtype);
221 };
222
223 template<int dimension, typename gltype, const char *strtype, void (*upd)(CGparameter, const gltype *)>
224 struct uniform2_i : uniform_i
225 {
226 gltype data[dimension];
227
228 void update ()
229 {
230 if (dirty)
231 {
232 //upd (param, data);
233 dirty = false;
234 }
235 }
236
237 uniform2_i () : uniform_i (strtype) { }
238 };
239
240 template<int dimension, const char *strtype, void (*update)(CGparameter, const GLfloat *)>
241 struct uniform_f_i : uniform2_i<dimension, GLfloat, strtype, update>
242 {
243 };
244
245 struct uniform_1f_i : uniform_f_i<1, str_float, cgGLSetParameter1fv> {
246 void operator =(GLfloat v)
247 {
248 data[0] = v;
249 dirty = true;
250 }
251 };
252
253 struct uniform_2f_i : uniform_f_i<2, str_vec2, cgGLSetParameter2fv> { };
254
255 struct uniform_3f_i : uniform_f_i<3, str_vec3, cgGLSetParameter3fv> {
256 void operator =(const vec3 &v)
257 {
258 data[0] = v.x;
259 data[1] = v.y;
260 data[2] = v.z;
261 dirty = true;
262 }
263 };
264
265 struct uniform_4f_i : uniform_f_i<4, str_vec4, cgGLSetParameter4fv> {
266 #if 0
267 void operator =(const gl::matrix &m)
268 {
269 memcpy (data, m.data, 16 * sizeof (GLfloat));
270 dirty = true;
271 }
272 #endif
273 };
274
275 struct uniform_matrix_2f_i : uniform_f_i< 4, str_mat2, cgGLSetMatrixParameterfc> { };
276 struct uniform_matrix_3f_i : uniform_f_i< 9, str_mat3, cgGLSetMatrixParameterfc> { };
277 struct uniform_matrix_4f_i : uniform_f_i<16, str_mat4, cgGLSetMatrixParameterfc> { };
278
279 template<class var_i>
280 struct var_ref : ref<var_i>
281 {
282 var_ref (const char *glname = 0)
283 : ref<var_i> (*new var_i)
284 {
285 if (glname)
286 strcpy ((*this)->name, glname);
287 }
288 };
289
290 typedef var_ref<uniform_1f_i> uniform_1f;
291 typedef var_ref<uniform_2f_i> uniform_2f;
292 typedef var_ref<uniform_3f_i> uniform_3f;
293 typedef var_ref<uniform_4f_i> uniform_4f;
294 typedef var_ref<uniform_matrix_2f_i> uniform_matrix_2f;
295 typedef var_ref<uniform_matrix_3f_i> uniform_matrix_3f;
296 typedef var_ref<uniform_matrix_4f_i> uniform_matrix_4f;
297
298 struct stream_i : var_i
299 {
300 void build (shader_builder &b);
301 void build_decl (ostringstream &b);
302 stream_i (const char *strtype) : var_i (strtype) { }
303 };
304
305 template<int dimension, GLenum gltype, const char *strtype>
306 struct varying_i : stream_i
307 {
308 varying_i (const char *glname)
309 : stream_i (strtype)
310 {
311 strcpy (name, glname);
312 }
313
314 void set (GLsizei stride, GLvoid *ptr)
315 {
316 //cgGLSetParameterPointer (param, dimension, gltype, stride, ptr);
317 }
318 };
319
320 template<int dimension, const char *strtype>
321 struct varying_f_i : varying_i<dimension, GL_FLOAT, strtype>
322 {
323 varying_f_i (const char *glname) : varying_i<dimension, GL_FLOAT, strtype> (glname) { }
324
325 void set (const gl::vertex_buffer_object &vb, GLint offset)
326 {
327 varying_i<dimension, GL_FLOAT, strtype>::set (gl::format_stride (vb.format), (GLvoid *)(long)offset);
328 }
329 };
330
331 struct varying_1f_i : varying_f_i<1, str_float>
332 {
333 varying_1f_i (const char *glname) : varying_f_i<1, str_float> (glname) { }
334 };
335
336 struct varying_2f_i : varying_f_i<2, str_vec2>
337 {
338 varying_2f_i (const char *glname) : varying_f_i<2, str_vec2> (glname) { }
339
340 void set_t (const gl::vertex_buffer_object &vb)
341 {
342 set (vb, gl::format_offset_t (vb.format));
343 }
344 };
345
346 struct varying_3f_i : varying_f_i<3, str_vec3>
347 {
348 varying_3f_i (const char *glname) : varying_f_i<3, str_vec3> (glname) { }
349
350 void set_p (const gl::vertex_buffer_object &vb)
351 {
352 set (vb, gl::format_offset_p (vb.format));
353 }
354
355 void set_n (const gl::vertex_buffer_object &vb)
356 {
357 set (vb, gl::format_offset_n (vb.format));
358 }
359 };
360
361 struct varying_4f_i : varying_f_i<4, str_vec4>
362 {
363 varying_4f_i (const char *glname) : varying_f_i<4, str_vec4> (glname) { }
364 };
365
366 typedef var_ref<varying_1f_i> varying_1f;
367 typedef var_ref<varying_2f_i> varying_2f;
368 typedef var_ref<varying_3f_i> varying_3f;
369 typedef var_ref<varying_4f_i> varying_4f;
370
371 struct temporary_i : var_i
372 {
373 void build (shader_builder &b);
374
375 temporary_i (const char *strtype);
376 };
377
378 template<const char *strtype>
379 struct temp_ref : ref<temporary_i>
380 {
381 temp_ref ()
382 : ref<temporary_i> (*new temporary_i (strtype))
383 {
384 }
385
386 template<typename expr>
387 const temp_ref &operator =(const expr &e) const;
388 };
389
390 typedef temp_ref<str_float> temp_1f;
391 typedef temp_ref<str_vec2> temp_2f;
392 typedef temp_ref<str_vec3> temp_3f;
393 typedef temp_ref<str_vec4> temp_4f;
394 typedef temp_ref<str_mat2> temp_matrix_2f;
395 typedef temp_ref<str_mat3> temp_matrix_3f;
396 typedef temp_ref<str_mat4> temp_matrix_4f;
397
398 template<GLenum gltype, const char *strtype>
399 struct sampler_i : uniform_i
400 {
401 GLuint texture;
402
403 void update ()
404 {
405 if (dirty)
406 {
407 //cgGLSetTextureParameter (param, texture);
408 dirty = false;
409 }
410 }
411
412 void begin ()
413 {
414 cgGLEnableTextureParameter (texture);
415 }
416
417 sampler_i (GLuint texturename) : uniform_i (strtype), texture (texturename) { }
418 };
419
420 struct sampler_1d_i : sampler_i<CG_SAMPLER1D, str_sampler_1d>
421 {
422 sampler_1d_i (GLuint texturename) : sampler_i<CG_SAMPLER1D, str_sampler_1d> (texturename) { }
423 };
424
425 struct sampler_1d_shadow_i : sampler_i<CG_SAMPLER1D, str_sampler_1d_shadow>
426 {
427 sampler_1d_shadow_i (GLuint texturename) : sampler_i<CG_SAMPLER1D, str_sampler_1d_shadow> (texturename) { }
428 };
429
430 struct sampler_2d_i : sampler_i<CG_SAMPLER2D, str_sampler_2d>
431 {
432 sampler_2d_i (GLuint texturename) : sampler_i<CG_SAMPLER2D, str_sampler_2d> (texturename) { }
433 };
434
435 struct sampler_2d_shadow_i : sampler_i<CG_SAMPLER2D, str_sampler_2d_shadow>
436 {
437 sampler_2d_shadow_i (GLuint texturename) : sampler_i<CG_SAMPLER2D, str_sampler_2d_shadow> (texturename) { }
438 };
439
440 struct sampler_2d_rect_i : sampler_i<CG_SAMPLERRECT, str_sampler_2d_rect>
441 {
442 sampler_2d_rect_i (GLuint texturename) : sampler_i<CG_SAMPLERRECT, str_sampler_2d_rect> (texturename) { }
443 };
444
445 struct sampler_2d_rect_shadow_i : sampler_i<CG_SAMPLERRECT, str_sampler_2d_rect_shadow>
446 {
447 sampler_2d_rect_shadow_i (GLuint texturename) : sampler_i<CG_SAMPLERRECT, str_sampler_2d_rect_shadow> (texturename) { }
448 };
449
450 struct sampler_3d_i : sampler_i<CG_SAMPLER3D, str_sampler_3d>
451 {
452 sampler_3d_i (GLuint texturename) : sampler_i<CG_SAMPLER3D, str_sampler_3d> (texturename) { }
453 };
454
455 struct sampler_3d_rect_i : sampler_i<CG_SAMPLER3D, str_sampler_3d_rect>
456 {
457 sampler_3d_rect_i (GLuint texturename) : sampler_i<CG_SAMPLER3D, str_sampler_3d_rect> (texturename) { }
458 };
459
460 struct sampler_cube_i : sampler_i<CG_SAMPLERCUBE, str_sampler_cube>
461 {
462 sampler_cube_i (GLuint texturename) : sampler_i<CG_SAMPLERCUBE, str_sampler_cube> (texturename) { }
463 };
464
465 typedef auto_ref1<sampler_1d_i, GLuint> sampler_1d;
466 typedef auto_ref1<sampler_1d_shadow_i, GLuint> sampler_1d_shadow;
467 typedef auto_ref1<sampler_2d_i, GLuint> sampler_2d;
468 typedef auto_ref1<sampler_2d_shadow_i, GLuint> sampler_2d_shadow;
469 typedef auto_ref1<sampler_2d_rect_i, GLuint> sampler_2d_rect;
470 typedef auto_ref1<sampler_2d_rect_shadow_i, GLuint> sampler_2d_rect_shadow;
471 typedef auto_ref1<sampler_3d_i, GLuint> sampler_3d;
472 typedef auto_ref1<sampler_3d_rect_i, GLuint> sampler_3d_rect;
473 typedef auto_ref1<sampler_cube_i, GLuint> sampler_cube;
474
475 struct fragment_const_string_i : fragment_i
476 {
477 const char *str;
478
479 void build (shader_builder &b);
480
481 fragment_const_string_i (const char *str) : str(str) { }
482 };
483
484 typedef auto_ref1<fragment_const_string_i, const char *> fragment_const_string;
485
486 struct fragment_string_i : fragment_i
487 {
488 char *str;
489
490 void build (shader_builder &b);
491
492 fragment_string_i (const char *str) : str (strdup (str)) { }
493 ~fragment_string_i ();
494 };
495
496 struct fragment_vector_i : fragment_i, vector<fragment>
497 {
498 void build (shader_builder &b);
499
500 template<class fragment_i>
501 void append (const ref<fragment_i> &f)
502 {
503 push_back (f);
504 }
505
506 void append_const (const char *s)
507 {
508 push_back (*new fragment_const_string_i (s));
509 }
510
511 void append_string (const char *s)
512 {
513 push_back (*new fragment_string_i (s));
514 }
515
516 #if 0
517 fragment_vector_i &operator <<(statement_i &f)
518 {
519 push_back (*new fragment_const_string_i (" "));
520
521 for (vector<fragment>::iterator i = f.begin (); i != f.end (); i++)
522 push_back (*i);
523
524 push_back (*new fragment_const_string_i (";\n"));
525 return *this;
526 }
527 #endif
528 };
529
530 typedef ref<fragment_vector_i> fragment_vector;
531
532 struct shader_object_i : fragment_vector_i
533 {
534 GLenum type;
535 GLuint id; // GLhandleARB, but 2.0 will use uint
536
537 string source ();
538 void compile ();
539 void start ();
540 void stop ();
541
542 shader_object_i (GLenum type);
543 ~shader_object_i ();
544 };
545
546 extern shader_object_i *cur; // record actions to this shader
547
548 template<GLenum type>
549 struct shader_object : ref<shader_object_i>
550 {
551 shader_object ()
552 : ref<shader_object_i> (*new shader_object_i (type))
553 {
554 }
555 };
556
557 typedef shader_object<GL_VERTEX_SHADER_ARB> vertex_shader;
558 typedef shader_object<GL_FRAGMENT_SHADER_ARB> fragment_shader;
559
560 template<typename T>
561 struct sl_append
562 {
563 T t;
564
565 sl_append (const T &t) : t(t) { }
566
567 void operator ()() const
568 {
569 cur->push_back (t);
570 }
571 };
572
573 template<int length>
574 struct sl_string
575 {
576 char str[length];
577
578 void operator ()() const
579 {
580 cur->push_back (*new fragment_string_i (str));
581 }
582 };
583
584 // only floats
585 struct sl_float
586 {
587 const GLfloat c;
588
589 sl_float (GLfloat c) : c(c) { }
590
591 void operator ()() const
592 {
593 char s[64];
594 sprintf (s, "%g", c);
595 cur->append_string (s);
596 }
597 };
598
599 template<class A, class B>
600 inline sl_expr< sl_concat2<A, B> >
601 concat (const A &a, const B &b)
602 {
603 typedef sl_concat2<A, B> expr;
604 return sl_expr<expr> (expr (a, b));
605 }
606
607 template<class A, class B, class C>
608 inline sl_expr< sl_concat3<A, B, C> >
609 concat (const A &a, const B &b, const C &c)
610 {
611 typedef sl_concat3<A, B, C> expr;
612 return sl_expr<expr> (expr (a, b, c));
613 }
614
615 template<class A, class B, class C, class D>
616 inline sl_expr< sl_concat4<A, B, C, D> >
617 concat (const A &a, const B &b, const C &c, const D &d)
618 {
619 typedef sl_concat4<A, B, C, D> expr;
620 return sl_expr<expr> (expr (a, b, c, d));
621 }
622
623 template<typename expr>
624 struct sl_convert
625 {
626 typedef sl_expr<expr> T;
627 static inline const T &convert (const T &e)
628 {
629 return e;
630 }
631 };
632
633 template<>
634 struct sl_convert<GLfloat>
635 {
636 typedef sl_expr<sl_float> T;
637 static inline const T convert (GLfloat f)
638 {
639 return sl_float (f);
640 }
641 };
642
643 template<>
644 struct sl_convert<vec3>
645 {
646 typedef sl_expr< sl_string<256> > T;
647 static inline const T convert (const vec3 &v)
648 {
649 sl_string<256> s;
650 sprintf (s.str, "vec3 (%g, %g, %g)", v.x, v.y, v.z);
651 return s;
652 }
653 };
654
655 template<>
656 struct sl_convert<vec4>
657 {
658 typedef sl_expr< sl_string<256> > T;
659 static inline const T convert (const vec4 &v)
660 {
661 sl_string<256> s;
662 sprintf (s.str, "vec4 (%g, %g, %g, %g)", v.x, v.y, v.z, v.w);
663 return s;
664 }
665 };
666
667 template<>
668 template<class V>
669 struct sl_convert< var_ref<V> >
670 {
671 typedef sl_expr< sl_append< var_ref<V> > > T;
672 static inline const T convert (const var_ref<V> &v)
673 {
674 return sl_append< var_ref<V> > (v);
675 }
676 };
677
678 template<>
679 struct sl_convert<glvar>
680 {
681 typedef sl_expr< sl_append<glvar> > T;
682 static inline const T convert (const glvar &v)
683 {
684 return sl_append<glvar> (v);
685 }
686 };
687
688 template<>
689 template<const char *strtype>
690 struct sl_convert< temp_ref<strtype> >
691 {
692 typedef sl_expr< sl_append< temp_ref<strtype> > > T;
693 static inline const T convert (const temp_ref<strtype> &v)
694 {
695 return sl_expr< sl_append< temp_ref<strtype> > >(
696 sl_append< temp_ref<strtype> > (v)
697 );
698 }
699 };
700
701 template<class fragment, typename expr>
702 inline void sl_assign (const fragment &f, const expr &e)
703 {
704 cur->append_const (" ");
705 cur->append (f);
706 cur->append_const (" = ");
707 sl_convert<expr>::convert (e) ();
708 cur->append_const (";\n");
709 }
710
711 template<class type>
712 template<typename expr>
713 inline const auto_lvalue_ref0<type> &auto_lvalue_ref0<type>::operator =(const expr &e) const
714 {
715 sl_assign (*this, e);
716 return *this;
717 }
718
719 template<class type, typename arg1>
720 template<typename expr>
721 inline const auto_lvalue_ref1<type,arg1> &auto_lvalue_ref1<type,arg1>::operator =(const expr &e) const
722 {
723 sl_assign (*this, e);
724 return *this;
725 }
726
727 template<const char *strtype>
728 template<typename expr>
729 inline const temp_ref<strtype> &temp_ref<strtype>::operator =(const expr &e) const
730 {
731 sl_assign (*this, e);
732 return *this;
733 }
734
735 struct sl_append_const_string
736 {
737 fragment_const_string str;
738 sl_append_const_string (const char *s)
739 : str (s)
740 { }
741
742 void operator ()() const
743 {
744 cur->push_back (str);
745 }
746 };
747
748 # define SHADER_BINOP(op, str) \
749 extern const sl_append_const_string str_ ## str; \
750 template<typename A, typename B> \
751 inline const sl_expr< sl_concat3< typename sl_convert<A>::T, \
752 sl_append_const_string, \
753 typename sl_convert<B>::T > > \
754 operator op(const A &a, const B &b) \
755 { \
756 return concat (sl_convert<A>::convert (a), str_ ## str, sl_convert<B>::convert (b)); \
757 }
758
759 SHADER_BINOP (+, plus);
760 SHADER_BINOP (-, minus);
761 SHADER_BINOP (*, mul);
762 SHADER_BINOP (/, div);
763
764 # undef SHADER_BINOP
765
766 void debdebdebdebug ();//D
767 }
768
769 #endif
770