--- libgender/shader.C 2004/10/30 00:17:28 1.23 +++ libgender/shader.C 2004/11/05 19:55:15 1.31 @@ -16,7 +16,7 @@ abort (); } - void refcounted::refcnt_dec () const + void refcounted::refcnt_destroy () const { if (!--refcnt) delete this; // quite a bit of code... @@ -42,8 +42,8 @@ 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) { } @@ -51,108 +51,46 @@ { } +#if 0 stream_i::stream_i (const char *strtype) : var_i (strtype) { sprintf (name, "V%d", ++next_id); } +#endif temporary_i::temporary_i (const char *strtype) - : var_i (strtype) + : var_i (0, strtype) { sprintf (name, "T%d", ++next_id); } - uniform_i::uniform_i (const char *strtype) - : var_i (strtype) - { - sprintf (name, "U%d", ++next_id); - } - - fragment_string_i::~fragment_string_i () + varying_i::varying_i (const char *strtype) + : var_i ("varying", strtype) { - free (str); - } - - //////////////////////////////////////////////////////////////////////////// - - void var_i::build_decl (ostringstream &b) - { - b << typestr << ' ' << name; - } - - void uniform_i::build_decl (ostringstream &b) - { - b << "uniform " << typestr << ' ' << name; + sprintf (name, "V%d", ++next_id); } - void stream_i::build_decl (ostringstream &b) + uniform_i::uniform_i (const char *strtype) + : var_i ("uniform", strtype) { - b << typestr << ' ' << name; + sprintf (name, "U%d", ++next_id); } //////////////////////////////////////////////////////////////////////////// - void gluvar_i::build (shader_builder &b) - { - b << name; - } - - void var_i::build (shader_builder &b) - { - b << name; - } - - void uniform_i::build (shader_builder &b) + void var_i::operator ()() const { - 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 0 - if (find (b.streams.begin (), b.streams.end (), var (*this)) == b.streams.end ()) - b.streams.push_back (*this); -#endif - } - - 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); - } + shader_builder::cur->code << name; - 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"; + if (shader_builder::cur->first (this)) + { + if (domainstr) + shader_builder::cur->global << domainstr << ' ' << typestr << ' ' << name << ";\n"; + else + shader_builder::cur->local << " " << typestr << ' ' << name << ";\n"; + } } -#endif //////////////////////////////////////////////////////////////////////////// @@ -173,55 +111,6 @@ glDeleteObjectARB (id); } - void shader_object_i::start () - { - clear (); - cur = this; - } - - void shader_object_i::stop () - { - cur = 0; - } - - string shader_object_i::source () - { - 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"; - } - -#if 0 - // 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"; - } -#endif - - os << "\nvoid main (void)\n{\n"; - - 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 (); - } - static string linify (const string &s) { ostringstream o; @@ -242,60 +131,34 @@ return o.str (); } - void shader_object_i::compile () - { - string src = source (); - const char *sptr = src.data (); - const int slen = src.size (); - - printf ("%s\n", linify (src).c_str ()); - glShaderSourceARB (id, 1, &sptr, &slen); - glCompileShaderARB (id); - - GLint compiled; - glGetObjectParameterivARB (id, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); - - if (!compiled) - { - char infolog[8192]; - glGetInfoLogARB (id, 8192, NULL, infolog); - printf ("%s\n", linify (src).c_str ()); - printf ("%s\n", infolog); - abort (); - } - } - //////////////////////////////////////////////////////////////////////////// - program_object *program_object::cur = 0; - GLint uniform_i::location () { - assert (program_object::cur); + assert (program_object_i::cur); - GLint &rid = program_object::cur->uloc[this]; + GLint &rid = program_object_i::cur->uloc[this]; if (!rid) - rid = glGetUniformLocationARB (program_object::cur->id, name); + rid = glGetUniformLocationARB (program_object_i::cur->id, name); return rid; } - program_object::program_object () + program_object_i *program_object_i::cur; + + program_object_i::program_object_i () { id = glCreateProgramObjectARB (); assert (id); - - glAttachObjectARB (id, vsh->id); - glAttachObjectARB (id, fsh->id); } - program_object::~program_object () + program_object_i::~program_object_i () { glDeleteProgramsARB (1, &id); } - void program_object::link () + void program_object_i::link () { glLinkProgramARB (id); @@ -313,146 +176,134 @@ uloc.clear (); } - void program_object::enable () + void program_object_i::enable () { - glUseProgramObjectARB (id); - //TODO: set samplers here - cur = this; + if (this != cur) + { + glUseProgramObjectARB (id); + //TODO: set samplers here? + cur = this; + } } - void program_object::disable () + void program_object_i::disable () { - //TODO: clear samplers here + //TODO: clear samplers here? glUseProgramObjectARB (0); cur = 0; } - void sl_func0::begin () const - { - cur->append_string (name_par); - } + static map progcache; - void sl_func0::comma () const + program_object get_program (const string &vsh, const string &fsh) { - cur->append (compile::str_comma); - } + string idx = vsh + "\0" + fsh; - void sl_func0::end () const - { - compile::str_rpar (); - } + map::iterator i = progcache.find (idx); - void sl_float::operator ()() const - { - char s[20]; - sprintf (s, "%g", c); - cur->append_string (s); + 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); 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); 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); return s; } - namespace compile { - - 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"); - - 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_lt (" < "); - const sl_append_const_string str_lte (" <= "); - const sl_append_const_string str_eq (" == "); - const sl_append_const_string str_ne (" != "); - const sl_append_const_string str_gte (" >= "); - const sl_append_const_string str_gt (" > "); - - const sl_append_const_string str_lpar ("("); - const sl_append_const_string str_rpar (")"); - - void swizzle_mask (sl_string<7> &s, int mask) - { - static const char channel[4] = { 'x', 'y', 'z', 'w' }; - - char *str = s.str; + shader_builder *shader_builder::cur = 0; - *str++ = ')'; - *str++ = '.'; - - while (mask) - { - int c = mask % 5; - mask /= 5; - - if (c) - *str++ = channel[c - 1]; - } + bool shader_builder::first (const void *p) + { + if (seen.find (p) == seen.end ()) + { + seen.insert (p); + return true; + } - *str++ = 0; - } + return false; } - void debdebdebdebug ()//D + void shader_builder::start () { - return; - - using namespace compile; - - vertex_shader vsh; - - vsh->start (); - - temp_4f lightpos; - temp_4f wpos; + cur = new shader_builder; + } - lightpos = vec4 (0, 10, 0, 1); - wpos = model_view_matrix * vin.vertex; - vout.position = vin.vertex * model_view_matrix_inverse; - 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 (model_view_matrix_inverse_transpose) * vin.normal); - //vout.tex_coord[4] = normalize (xyz (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 (); + } } }