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