changed |= MATRIX;
}
+void Renderer::set_texture(Tag tag, const Texture *tex, const Sampler *samp)
+{
+ set_texture(tag, -1, tex, samp);
+}
+
+void Renderer::set_texture(Tag tag, int unit, const Texture *tex, const Sampler *samp)
+{
+ if(texture_stack.size()>state->texture_count)
+ {
+ BoundTexture &bt = texture_stack[state->texture_count];
+ if((!tag.id || bt.tag==tag) && (unit<0 || bt.unit==unit) && bt.texture==tex && bt.sampler==samp)
+ {
+ ++state->texture_count;
+ return;
+ }
+ else
+ flush_textures();
+ }
+
+ for(vector<BoundTexture>::iterator i=texture_stack.end(); i!=texture_stack.begin(); )
+ if((--i)->tag==tag && i->unit==unit)
+ {
+ i->replaced = texture_stack.size();
+ break;
+ }
+
+ texture_stack.push_back(BoundTexture());
+ BoundTexture &bound_tex = texture_stack.back();
+ bound_tex.tag = tag;
+ bound_tex.unit = unit;
+ bound_tex.texture = tex;
+ bound_tex.sampler = samp;
+ state->texture_count = texture_stack.size();
+}
+
void Renderer::set_texture(const Texture *t, const Sampler *s)
{
- state->texture = t;
- state->sampler = s;
- state->texturing = 0;
+ set_texture(Tag(), 0, t, s);
+}
+
+void Renderer::flush_textures()
+{
+ for(unsigned i=0; i<texture_stack.size(); ++i)
+ {
+ BoundTexture &bt = texture_stack[i];
+ if(i>=state->texture_count && bt.unit>=0)
+ {
+ Texture::unbind_from(bt.unit);
+ Sampler::unbind_from(bt.unit);
+ }
+ else if(bt.replaced>=static_cast<int>(state->texture_count))
+ bt.replaced = -1;
+ }
+
+ texture_stack.erase(texture_stack.begin()+state->texture_count, texture_stack.end());
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void Renderer::set_texturing(const Texturing *t)
{
- state->texturing = t;
- state->texture = 0;
- state->sampler = 0;
+ if(t)
+ {
+ unsigned n_units = TexUnit::get_n_units();
+ for(unsigned i=0; i<n_units; ++i)
+ if(const Texture *tex = t->get_attached_texture(i))
+ set_texture(Tag(), i, tex, t->get_attached_sampler(i));
+ }
}
+#pragma GCC diagnostic pop
unsigned Renderer::allocate_effect_texunit()
{
void Renderer::add_shader_data(const ProgramData &d)
{
- if(state->shdata_count<shdata_stack.size() && shdata_stack[state->shdata_count]==&d)
- ++state->shdata_count;
- else
+ if(state->shdata_count<shdata_stack.size())
{
- flush_shader_data();
- shdata_stack.push_back(&d);
- state->shdata_count = shdata_stack.size();
- changed |= SHADER_DATA;
+ const BoundProgramData &top = shdata_stack.back();
+ if(top.shdata==&d && top.generation==d.get_generation())
+ {
+ ++state->shdata_count;
+ return;
+ }
}
+
+ flush_shader_data();
+ shdata_stack.push_back(&d);
+ state->shdata_count = shdata_stack.size();
+ changed |= SHADER_DATA;
}
void Renderer::flush_shader_data()
shdata_stack.clear();
excluded.clear();
- Texturing::unbind();
- Texture::unbind_from(0);
+ for(vector<BoundTexture>::iterator i=texture_stack.begin(); i!=texture_stack.end(); ++i)
+ if(i->unit>=0)
+ {
+ Texture::unbind_from(i->unit);
+ Sampler::unbind_from(i->unit);
+ }
Clipping::unbind();
Program::unbind();
VertexSetup::unbind();
/* We (mostly) let the objects themselves figure out if the binding has
changed */
- if(state->texturing)
- state->texturing->bind();
- else
+ if(state->texture_count<texture_stack.size())
+ flush_textures();
+
+ for(vector<BoundTexture>::const_iterator i=texture_stack.begin(); i!=texture_stack.end(); ++i)
{
- Texturing::unbind();
- if(state->texture)
+ int unit = (i->tag.id ? state->shprog->get_uniform_binding(i->tag) : i->unit);
+ if(unit>=0)
{
- if(state->sampler)
- state->sampler->bind_to(0);
- else
- Sampler::unbind_from(0);
- state->texture->bind_to(0);
+ if(i->texture)
+ i->texture->bind_to(unit);
+ if(i->sampler)
+ i->sampler->bind_to(unit);
+ i->unit = unit;
}
- else
- Texture::unbind_from(0);
}
if(state->clipping)
standard_shdata.uniform("eye_obj_matrix", state->modelview_matrix);
LinAl::SquareMatrix<float, 3> nm = state->modelview_matrix.block<3, 3>(0, 0);
nm = transpose(invert(nm));
- standard_shdata.uniform_matrix3("eye_obj_normal_matrix", &nm(0, 0));
+ standard_shdata.uniform("eye_obj_normal_matrix", nm);
changed = (changed&~MATRIX)|STANDARD_SHDATA;
}
{
if(extra_shdata)
shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end());
- for(vector<const ProgramData *>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
- (*i)->apply();
+ for(vector<BoundProgramData>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
+ i->shdata->apply();
changed &= ~SHADER_DATA;
}
}
+Renderer::BoundTexture::BoundTexture():
+ unit(-1),
+ texture(0),
+ sampler(0),
+ replaced(-1)
+{ }
+
+
+Renderer::BoundProgramData::BoundProgramData(const ProgramData *d):
+ shdata(d),
+ generation(0)
+{ }
+
+
Renderer::State::State():
camera(0),
- texture(0),
- texturing(0),
+ texture_count(0),
lowest_effect_texunit(TexUnit::get_n_units()),
material(0),
lighting(0),