--- libgender/material.C 2004/11/04 04:46:58 1.35 +++ libgender/material.C 2005/08/09 23:58:43 1.65 @@ -8,12 +8,8 @@ #include "view.h" #include "util.h" -material::~material () -{ -} - GLuint -texture::load_texture (SDL_Surface * surface, GLfloat * tex2oord) +texture::load_texture (SDL_Surface * surface, GLfloat * tex2oord, int flags) { GLuint name; SDL_Surface *image; @@ -59,50 +55,80 @@ glGenTextures (1, &name); glBindTexture (GL_TEXTURE_2D, name); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - glTexImage2D (GL_TEXTURE_2D, - 0, - GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, flags & DISABLE_MIPMAP ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, flags & DISABLE_MIPMAP ? GL_FALSE : GL_TRUE); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); + + if (flags & CLAMP) + { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + } + SDL_FreeSurface (image); /* No longer needed */ return name; } +material::~material () +{ +} + void material::enable (view &ctx) { - pass::matmap_t &matmap = ctx.pass_data->matmap; + pass_data::matmap_t &matmap = ctx.pass->matmap; - pass::matmap_t::iterator i = matmap.find (this); - shader::program_object *p; + pass_data::matmap_t::iterator i = matmap.find (this); if (i == matmap.end ()) { - shader::program_object po; + string vsh_src, fsh_src; shader::shader_builder::start (); + + if (ctx.pass->l) + ctx.pass->l->vsh (); + vsh (ctx); - if (ctx.pass_data->l) - ctx.pass_data->l->vsh (); + // compute logarithmic depth - see the frustum matrix in view.C + { + using namespace shader::compile; + + temp_1f lz; + + // TODO: negative z is not calculated in an a very acceptable way + lz = z (vout.position); + lz = sign (lz) * (log (abs (lz) + exp (1e0)) - 1e0) / log (1e30); + z (vout.position) = lz * w (vout.position); + } - po->vsh->compile (shader::shader_builder::stop ()); + vsh_src = shader::shader_builder::stop (); shader::shader_builder::start (); - shader::compile::fout.frag_color = shader::compile::float4 (1., 1., 0., 1.); - fsh (ctx); - po->fsh->compile (shader::shader_builder::stop ()); - po->link (); + if (ctx.pass->l) + { + ctx.pass->l->fsh (); + fsh (ctx); + } + else + // many drivers need both vertex and fragment shader, 'caboom!' otherwise + shader::compile::fout.frag_color = shader::compile::float4 (0., 0., 0., 0.); + + fsh_src = shader::shader_builder::stop (); - matmap.insert (pass::matmap_t::value_type (this, po)); + shader::program_object po = shader::get_program (vsh_src, fsh_src); + matmap.insert (pass_data::matmap_t::value_type (this, po)); - p = &po; + po->enable (); } else - p = &i->second; + i->second->enable (); - (*p)->enable (); + if (ctx.pass->l) + ctx.pass->l->enable (ctx); } void material::disable (view &ctx) @@ -116,8 +142,157 @@ { } -static shader::varying_3f normal, lightvec; +skybox_material::skybox_material () +: tex (0) +{ +} + +void skybox_material::enable (view &ctx) +{ + material::enable (ctx); +} + +void skybox_material::disable (view &ctx) +{ + material::disable (ctx); +} + +static shader::varying_2f skybox_texcoord; + +void skybox_material::vsh (view &ctx) +{ + using namespace shader::compile; + + std_vsh (); + skybox_texcoord = xy (vin.tex_coord[0]); +} + +void skybox_material::fsh (view &ctx) +{ + using namespace shader::compile; + + xyz (fout.frag_color) = texture_2d (tex, skybox_texcoord); +} + +void mat_timed::enable (view &ctx) +{ + material::enable (ctx); + + time->set (timer::now); + sh_colour->set (vec3 (255, 0, 0) * (1.F / 255.F)); +} + +void mat_timed::disable (view &ctx) +{ + material::disable (ctx); +} + +void mat_timed::vsh (view &ctx) +{ + using namespace shader::compile; + std_vsh (); + + if (ctx.pass->l) + f_normal = normal_matrix * vin.normal; +} + +void mat_timed::fsh (view &ctx) +{ + using namespace shader::compile; + + if (ctx.pass->l) + { + temp_1f fac; + temp_3f normal; + + normal = f_normal + 0.3 * pow (sin (f_normal * 3.14159 + time), 3); + + fac = dot (normalize (normal), normalize (ctx.pass->l->sh_lightvec)); + + xyz (fout.frag_color) = fac * float3 (0.1,0.5,1);//ctx.pass->l->sh_colour * sh_colour * fac; + } +} + +void mat_gouraud_shaded::enable (view &ctx) +{ + material::enable (ctx); + + sh_colour->set (vec3 (c.r, c.g, c.b) * (1.F / 255.F)); +} + +void mat_gouraud_shaded::disable (view &ctx) +{ + material::disable (ctx); +} + +void mat_gouraud_shaded::vsh (view &ctx) +{ + using namespace shader::compile; + std_vsh (); + + if (ctx.pass->l) + f_normal = normal_matrix * vin.normal; +} + +void mat_gouraud_shaded::fsh (view &ctx) +{ + using namespace shader::compile; + + if (ctx.pass->l) + { + temp_1f fac; + + fac = dot (normalize (f_normal), normalize (ctx.pass->l->sh_lightvec)); + + xyz (fout.frag_color) = ctx.pass->l->sh_colour * sh_colour * fac; + } +} + +static shader::varying_3f f_normal; + +void mat_debug::enable (view &ctx) +{ + material::enable (ctx); + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + glDepthMask (1); +} + +void mat_debug::disable (view &ctx) +{ + material::disable (ctx); + + glDisable (GL_BLEND); + glDepthMask (0); +} + +void mat_debug::vsh (view &ctx) +{ + using namespace shader::compile; + std_vsh (); + + if (ctx.pass->l) + f_normal = normal_matrix * vin.normal; +} + +void mat_debug::fsh (view &ctx) +{ + using namespace shader::compile; + + if (ctx.pass->l) + { + temp_1f fac; + + fac = dot (normalize (f_normal), normalize (ctx.pass->l->sh_lightvec)); + + xyz (fout.frag_color) = float3 (1.,0.,0.); + w (fout.frag_color) = 0.1; + } +} + static shader::varying_2f texcoord; +static shader::varying_3f normal; void test_material::vsh (view &ctx) { @@ -125,11 +300,10 @@ std_vsh (); - if (ctx.pass_data->l) + if (ctx.pass->l) { texcoord = xy (vin.tex_coord[0]); normal = normal_matrix * vin.normal; - lightvec = xyz (ctx.pass_data->l->lightpos - model_view_matrix * vin.vertex); } } @@ -137,24 +311,27 @@ { using namespace shader::compile; - if (ctx.pass_data->l) + if (ctx.pass->l) { temp_3f lc; temp_1f fac; - lc = (*ctx.pass_data->l)(); - temp_3f rot1, rot2, rot3; - rot1 = yxz (texture_2d (normvar, texcoord) * 2.F - 1.F); - rot2 = float3 (x(rot1), -z(rot1), y(rot1)); - rot3 = float3 (-y(rot1), x(rot1), z(rot1)); + yxz (rot1) = (texture_2d (normvar, texcoord) * 2.F - 1.F); + + //rot1 = normal_matrix * rot1; + + rot2 = float3 (x(rot1), z(rot1), -y(rot1)); + rot3 = float3 (y(rot1), -x(rot1), z(rot1)); normal = mat3 (rot1, rot2, rot3) * normal; - fac = dot (normalize (normal), normalize (lightvec)); - fac = pow (max (fac, 0.0), 6); - xyz (fout.frag_color) = (texture_2d (texvar, texcoord) + 0.2F) * lc * fac; + fac = dot (normalize (normal), normalize (ctx.pass->l->sh_lightvec)); + fac = max (pow (max (fac, 0.0), 6), 0.3); + xyz (fout.frag_color) = (texture_2d (texvar, texcoord) + 0.2F) * fac + * ctx.pass->l->sh_colour; + //xyz (fout.frag_color) = lc * fac; } } @@ -173,4 +350,7 @@ } test_material *testmat; +mat_gouraud_shaded *testmat2; +mat_timed *testmat3; +mat_debug *debugmat;