--- libgender/shader.C 2004/10/23 21:55:13 1.4 +++ libgender/shader.C 2004/11/03 03:35:13 1.29 @@ -1,14 +1,25 @@ +#include + #include "shader.h" #include "shader_vars.h" +#include +#include + namespace shader { + using namespace std; + refcounted::~refcounted () { -#if 0 if (refcnt) abort (); -#endif + } + + void refcounted::refcnt_destroy () const + { + if (!--refcnt) + delete this; // quite a bit of code... } const char str_float [] = "float"; @@ -31,188 +42,242 @@ 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) - { - b << typestr << ' ' << name; - } - - void uniform_i::build_decl (ostringstream &b) + void var_i::operator ()() const { - 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) + int texture_units::unit_count = 8; + int texture_units::units[8] = { 7, 6, 5, 4, 3, 2, 1, 0 }; + + shader_object_i *cur = 0; + + shader_object_i::shader_object_i (GLenum type) + : type (type) { - b << name; + id = glCreateShaderObjectARB (type); + assert (id); } - void var_i::build (shader_builder &b) + shader_object_i::~shader_object_i () { - b << name; + glDeleteObjectARB (id); } - void uniform_i::build (shader_builder &b) + static string linify (const string &s) { - var_i::build (b); + ostringstream o; + + 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 ()); - if (find (b.refs.begin (), b.refs.end (), uniform (*this)) == b.refs.end ()) - b.refs.push_back (*this); + return o.str (); } - void stream_i::build (shader_builder &b) + //////////////////////////////////////////////////////////////////////////// + + GLint uniform_i::location () { - var_i::build (b); + assert (program_object_i::cur); + + GLint &rid = program_object_i::cur->uloc[this]; + + if (!rid) + rid = glGetUniformLocationARB (program_object_i::cur->id, name); - if (find (b.streams.begin (), b.streams.end (), var (*this)) == b.streams.end ()) - b.streams.push_back (*this); + return rid; } - void temporary_i::build (shader_builder &b) + program_object_i *program_object_i::cur; + + program_object_i::program_object_i () { - var_i::build (b); + id = glCreateProgramObjectARB (); + assert (id); - if (find (b.temps.begin (), b.temps.end (), var (*this)) == b.temps.end ()) - b.temps.push_back (*this); + glAttachObjectARB (id, vsh->id); + glAttachObjectARB (id, fsh->id); } - void fragment_vector_i::build (shader_builder &b) + program_object_i::~program_object_i () { - for (vector::iterator i = begin (); i != end (); i++) - (*i)->build (b); + glDeleteProgramsARB (1, &id); } - void fragment_const_string_i::build (shader_builder &b) + void program_object_i::link () { - b << str; + glLinkProgramARB (id); + + GLint linked; + glGetObjectParameterivARB (id, GL_OBJECT_LINK_STATUS_ARB, &linked); + + if (!linked) + { + char infolog[8192]; + glGetInfoLogARB (id, 8192, NULL, infolog); + printf ("LINK-INFOLOG<%s>\n", infolog); + abort (); + } + + uloc.clear (); } - void fragment_string_i::build (shader_builder &b) + void program_object_i::enable () { - b << str; + glUseProgramObjectARB (id); + //TODO: set samplers here + cur = this; } -#if 0 - void statement_i::build (shader_builder &b) + void program_object_i::disable () { - b << " "; - fragment_vector_i::build (b); - b << ";\n"; + //TODO: clear samplers here + glUseProgramObjectARB (0); + cur = 0; } -#endif - - //////////////////////////////////////////////////////////////////////////// - shader_object_i *cur = 0; + static map progcache; - shader_object_i::shader_object_i (GLenum type) - : type (type) + program_object get_program (const string &vsh, const string &fsh) { - id = glCreateShaderObjectARB (type); + string idx = vsh + "\0" + fsh; + + map::iterator i = progcache.find (idx); + + if (i != progcache.end ()) + return i->second; + + program_object p; + + p->vsh->compile (vsh); + p->fsh->compile (fsh); + p->link (); + + progcache.insert (pair (idx, p)); + + return p; } - shader_object_i::~shader_object_i () + const sl_expr< sl_string<60> > sl_convert< ::vec2 >::convert (const ::vec2 &v) { - glDeleteObjectARB (id); + sl_string<60> s; + sprintf (s.str, "vec2 (%g, %g)", v.x, v.y); + return s; } - void shader_object_i::start () + const sl_expr< sl_string<80> > sl_convert< ::vec3 >::convert (const ::vec3 &v) { - clear (); - cur = this; + sl_string<80> s; + sprintf (s.str, "vec3 (%g, %g, %g)", v.x, v.y, v.z); + return s; } - void shader_object_i::stop () + const sl_expr< sl_string<100> > sl_convert< ::vec4 >::convert (const ::vec4 &v) { - cur = 0; + sl_string<100> s; + sprintf (s.str, "vec4 (%g, %g, %g, %g)", v.x, v.y, v.z, v.w); + return s; } - string shader_object_i::source () - { - shader_builder b; - build (b); - ostringstream os; + shader_builder *shader_builder::cur = 0; - for (vector::iterator i = b.refs.begin (); i != b.refs.end (); i++) + bool shader_builder::first (const void *p) + { + if (seen.find (p) == seen.end ()) { - (*i)->build_decl (os); - os << ";\n"; + seen.insert (p); + return true; } - // 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"; - } + return false; + } - os << "\nvoid main (void)\n{\n"; + void shader_builder::start () + { + cur = new shader_builder; + } - for (vector::iterator i = b.temps.begin (); i != b.temps.end (); i++) - { - os << " "; - (*i)->build_decl (os); - os << ";\n"; - } + string shader_builder::stop () + { + ostringstream os; - os << "\n"; - os << b.source.str (); - os << "}\n"; + os << cur->global.str () + << "\nvoid main (void)\n" + << "{\n" + << cur->local.str () + << "\n" + << cur->code.str () + << "}\n"; + + delete cur; + cur = 0; return os.str (); } - void shader_object_i::compile () + void shader_object_i::compile (const string &source) { - string src = source (); - const char *sptr = src.data (); - const int slen = src.size (); + const char *sptr = source.data (); + const int slen = source.size (); - printf ("SOURCE<%s>\n", src.c_str ()); - abort (); + printf ("%s\n", linify (source).c_str ()); glShaderSourceARB (id, 1, &sptr, &slen); glCompileShaderARB (id); @@ -223,38 +288,11 @@ { char infolog[8192]; glGetInfoLogARB (id, 8192, NULL, infolog); - printf ("SOURCE<%s>\n", src.c_str ()); - printf ("INFOLOG<%s>\n", infolog); + printf ("%s\n", linify (source).c_str ()); + printf ("%s\n", infolog); abort (); } } - 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_rpar (")"); - - void debdebdebdebug ()//D - { - vertex_shader vsh; - fragment_shader fsh; - temp_4f t1, t2; - sampler_2d s2d (1); - - vsh->start (); - - temp_4f lightpos; - temp_3f wpos; - - lightpos = vec4 (10, -10, 0, 1); - wpos = gl.model_view_matrix_inverse_transpose * vin.normal; - vout.position = wpos; - - vsh->end (); - vsh->compile (); - } - }