--- libgender/shader.C 2004/10/24 02:13:43 1.12 +++ libgender/shader.C 2006/01/25 22:48:02 1.32 @@ -3,17 +3,20 @@ #include "shader.h" #include "shader_vars.h" +#include +#include + namespace shader { + using namespace std; + refcounted::~refcounted () { -#if 1 if (refcnt) abort (); -#endif } - void refcounted::refcnt_dec () const + void refcounted::refcnt_destroy () const { if (!--refcnt) delete this; // quite a bit of code... @@ -39,119 +42,60 @@ unsigned int var_i::next_id = 0; - var_i::var_i (const char *typestr) - : typestr (typestr) + var_i::var_i (const char *domainstr, const char *typestr) + : domainstr (domainstr), typestr (typestr) { - //param = cgCreateParameter (cg_context, cgtype); } var_i::~var_i () { - //cgDestroyParameter (param); } +#if 0 stream_i::stream_i (const char *strtype) : var_i (strtype) { - sprintf (name, "V%lx_%d", ((long)this >> 4) & 0xfff, ++next_id); + sprintf (name, "V%d", ++next_id); } +#endif temporary_i::temporary_i (const char *strtype) - : var_i (strtype) + : var_i (0, strtype) { - sprintf (name, "T%lx_%d", ((long)this >> 4) & 0xfff, ++next_id); + sprintf (name, "T%d", ++next_id); } - uniform_i::uniform_i (const char *strtype) - : var_i (strtype), dirty (true) + varying_i::varying_i (const char *strtype) + : var_i ("varying", strtype) { - sprintf (name, "U%lx_%d", ((long)this >> 4) & 0xfff, ++next_id); + sprintf (name, "V%d", ++next_id); } - fragment_string_i::~fragment_string_i () + uniform_i::uniform_i (const char *strtype) + : var_i ("uniform", strtype) { - free (str); + sprintf (name, "U%d", ++next_id); } //////////////////////////////////////////////////////////////////////////// - void var_i::build_decl (ostringstream &b) + void var_i::operator ()() const { - b << typestr << ' ' << name; - } - - void uniform_i::build_decl (ostringstream &b) - { - b << "uniform " << typestr << ' ' << name; - } + shader_builder::cur->code << name; - void stream_i::build_decl (ostringstream &b) - { - b << typestr << ' ' << name; + if (shader_builder::cur->first (this)) + { + if (domainstr) + shader_builder::cur->global << domainstr << ' ' << typestr << ' ' << name << ";\n"; + else + shader_builder::cur->local << " " << typestr << ' ' << name << ";\n"; + } } //////////////////////////////////////////////////////////////////////////// - void glvar_i::build (shader_builder &b) - { - b << name; - } - - void var_i::build (shader_builder &b) - { - b << name; - } - - void uniform_i::build (shader_builder &b) - { - var_i::build (b); - - if (find (b.refs.begin (), b.refs.end (), uniform (*this)) == b.refs.end ()) - b.refs.push_back (*this); - } - - void stream_i::build (shader_builder &b) - { - var_i::build (b); - - if (find (b.streams.begin (), b.streams.end (), var (*this)) == b.streams.end ()) - b.streams.push_back (*this); - } - - void temporary_i::build (shader_builder &b) - { - var_i::build (b); - - if (find (b.temps.begin (), b.temps.end (), var (*this)) == b.temps.end ()) - b.temps.push_back (*this); - } - - void fragment_vector_i::build (shader_builder &b) - { - for (vector::iterator i = begin (); i != end (); i++) - (*i)->build (b); - } - - void fragment_const_string_i::build (shader_builder &b) - { - b << str; - } - - void fragment_string_i::build (shader_builder &b) - { - b << str; - } - -#if 0 - void statement_i::build (shader_builder &b) - { - b << " "; - fragment_vector_i::build (b); - b << ";\n"; - } -#endif - - //////////////////////////////////////////////////////////////////////////// + int texture_units::unit_count = 8; + int texture_units::units[8] = { 7, 6, 5, 4, 3, 2, 1, 0 }; shader_object_i *cur = 0; @@ -167,91 +111,55 @@ glDeleteObjectARB (id); } - void shader_object_i::start () - { - clear (); - cur = this; - } - - void shader_object_i::stop () - { - cur = 0; - } - - string shader_object_i::source () + static string linify (const string &s) { - shader_builder b; - build (b); - ostringstream os; - - for (vector::iterator i = b.refs.begin (); i != b.refs.end (); i++) - { - (*i)->build_decl (os); - os << ";\n"; - } - - // not neccessary right now, as GLSL is rich on predefinitions - for (vector::iterator i = b.streams.begin (); i != b.streams.end (); i++) - { - os << "attribute "; - (*i)->build_decl (os); - os << ";\n"; - } + ostringstream o; - os << "\nvoid main (void)\n{\n"; + int b = 0, e; + int l = 1; + do { + o << setw (3) << l << ": "; + e = s.find ('\n', b); + if (e == string::npos) + e = s.size (); + + o << s.substr (b, e - b + 1); + b = e + 1; + l++; + } while (b < s.size ()); - for (vector::iterator i = b.temps.begin (); i != b.temps.end (); i++) - { - os << " "; - (*i)->build_decl (os); - os << ";\n"; - } - - os << "\n"; - os << b.source.str (); - os << "}\n"; - - return os.str (); + return o.str (); } - void shader_object_i::compile () + //////////////////////////////////////////////////////////////////////////// + + GLint uniform_i::location () { - string src = source (); - const char *sptr = src.data (); - const int slen = src.size (); + assert (program_object_i::cur); - printf ("SOURCE<%s>\n", src.c_str ()); - glShaderSourceARB (id, 1, &sptr, &slen); - glCompileShaderARB (id); + GLint &rid = program_object_i::cur->uloc[this]; - GLint compiled; - glGetObjectParameterivARB (id, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); + if (!rid) + rid = glGetUniformLocationARB (program_object_i::cur->id, name); - if (!compiled) - { - char infolog[8192]; - glGetInfoLogARB (id, 8192, NULL, infolog); - printf ("SOURCE<%s>\n", src.c_str ()); - printf ("INFOLOG<%s>\n", infolog); - abort (); - } + return rid; } - program_object::program_object () + program_object_i *program_object_i::cur; + + program_object_i::program_object_i () { id = glCreateProgramObjectARB (); assert (id); } - program_object::~program_object () + program_object_i::~program_object_i () { glDeleteProgramsARB (1, &id); } - void program_object::link () + void program_object_i::link () { - glAttachObjectARB (id, vsh->id); - glAttachObjectARB (id, fsh->id); glLinkProgramARB (id); GLint linked; @@ -264,121 +172,139 @@ printf ("LINK-INFOLOG<%s>\n", infolog); abort (); } - } - void sl_func0::begin () const - { - cur->append_string (name_par); + uloc.clear (); } - void sl_func0::comma () const + void program_object_i::enable () { - cur->append (str_comma); + if (this != cur) + { + glUseProgramObjectARB (id); + //TODO: set samplers here? + cur = this; + } } - void sl_func0::end () const + void program_object_i::disable () { - str_rpar (); + //TODO: clear samplers here? + glUseProgramObjectARB (0); + cur = 0; } - void sl_float::operator ()() const + static map progcache; + + program_object get_program (const string &vsh, const string &fsh) { - char s[20]; - sprintf (s, "%g", c); - cur->append_string (s); + string idx = vsh + "\0" + fsh; + + map::iterator i = progcache.find (idx); + + if (i != progcache.end ()) + return i->second; + + program_object p; + + if (vsh.size ()) + { + vertex_shader sh; + p->attach (sh); + sh->compile (vsh); + } + + if (fsh.size ()) + { + fragment_shader sh; + p->attach (sh); + sh->compile (fsh); + } + + p->link (); + + progcache.insert (pair (idx, p)); + + return p; } - const sl_convert< ::vec2 >::T sl_convert< ::vec2 >::convert (const ::vec2 &v) + const sl_expr< sl_string<60> > sl_convert< ::vec2 >::convert (const ::vec2 &v) { sl_string<60> s; - sprintf (s.str, "vec2 (%g, %g)", v.x, v.y); + sprintf (s.str, "vec2 (%e, %e)", v.x, v.y); return s; } - const sl_convert< ::vec3 >::T sl_convert< ::vec3 >::convert (const ::vec3 &v) + const sl_expr< sl_string<80> > sl_convert< ::vec3 >::convert (const ::vec3 &v) { sl_string<80> s; - sprintf (s.str, "vec3 (%g, %g, %g)", v.x, v.y, v.z); + sprintf (s.str, "vec3 (%e, %e, %e)", v.x, v.y, v.z); return s; } - const sl_convert< ::vec4 >::T sl_convert< ::vec4 >::convert (const ::vec4 &v) + const sl_expr< sl_string<100> > sl_convert< ::vec4 >::convert (const ::vec4 &v) { sl_string<100> s; - sprintf (s.str, "vec4 (%g, %g, %g, %g)", v.x, v.y, v.z, v.w); + sprintf (s.str, "vec4 (%e, %e, %e, %e)", v.x, v.y, v.z, v.w); return s; } - const fragment_const_string str_2sp (" "); - const fragment_const_string str_equal (" = "); - const fragment_const_string str_comma (", "); - const fragment_const_string str_endl (";\n"); + shader_builder *shader_builder::cur = 0; - const sl_append_const_string str_plus (" + "); - const sl_append_const_string str_minus (" - "); - const sl_append_const_string str_mul (" * "); - const sl_append_const_string str_div (" / "); - const sl_append_const_string str_mod (" % "); - - const sl_append_const_string str_lpar ("("); - const sl_append_const_string str_rpar (")"); - - void swizzle_mask (sl_string<7> &s, int mask) + bool shader_builder::first (const void *p) { - static const char channel[4] = { 'x', 'y', 'z', 'w' }; - - char *str = s.str; - - *str++ = ')'; - *str++ = '.'; - - while (mask) + if (seen.find (p) == seen.end ()) { - int c = mask % 5; - mask /= 5; - - if (c) - *str++ = channel[c - 1]; + seen.insert (p); + return true; } - *str++ = 0; + return false; } - - void debdebdebdebug ()//D + void shader_builder::start () { - vertex_shader vsh; - - vsh->start (); - - temp_4f lightpos; - temp_3f wpos; + cur = new shader_builder; + cur->code << scientific; + } - lightpos = vec4 (10, -10, 0, 1); - wpos = xyz (gl.model_view_matrix * vin.vertex); - vout.position = gl.model_view_matrix_inverse_transpose * vin.vertex; - vout.tex_coord[0] = vin.tex_coord[0]; - vout.tex_coord[1] = normalize (lightpos - wpos); - vout.tex_coord[2] = normalize (wpos); - vout.tex_coord[3] = normalize (xyz (gl.model_view_matrix_inverse_transpose) * vin.normal); - vout.tex_coord[4] = normalize (xyz (gl.projection_matrix_inverse_transpose) - wpos); + string shader_builder::stop () + { + ostringstream os; - vsh->end (); - //vsh->compile (); + os << cur->global.str () + << "\nvoid main (void)\n" + << "{\n" + << cur->local.str () + << "\n" + << cur->code.str () + << "}\n"; - fragment_shader fsh; + delete cur; + cur = 0; - fsh->start (); + return os.str (); + } - xyz (fout.frag_color) = noise3 (x (fin.frag_coord) * y (fin.frag_coord)); + void shader_object_i::compile (const string &source) + { + const char *sptr = source.data (); + const int slen = source.size (); - temp_1f spec_expon; - spec_expon = 200; + printf ("%s\n", linify (source).c_str ()); + glShaderSourceARB (id, 1, &sptr, &slen); + glCompileShaderARB (id); - fsh->end (); - fsh->compile (); + GLint compiled; + glGetObjectParameterivARB (id, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); - //abort (); + if (!compiled) + { + char infolog[8192]; + glGetInfoLogARB (id, 8192, NULL, infolog); + printf ("%s\n", linify (source).c_str ()); + printf ("%s\n", infolog); + abort (); + } } }