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

File Contents

# User Rev Content
1 root 1.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 root 1.2 template<class var_i>
280     struct var_ref : ref<var_i>
281 root 1.1 {
282 root 1.2 var_ref (const char *glname = 0)
283     : ref<var_i> (*new var_i)
284 root 1.1 {
285     if (glname)
286     strcpy ((*this)->name, glname);
287     }
288     };
289    
290 root 1.2 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 root 1.1
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 root 1.2 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 root 1.1
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 root 1.3 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 root 1.1 void debdebdebdebug ();//D
767     }
768    
769     #endif
770