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()
{
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();
excluded.erase(&renderable);
}
-void Renderer::render(const Renderable &renderable, const Tag &tag)
+void Renderer::render(const Renderable &renderable, Tag tag)
{
if(!excluded.count(&renderable))
renderable.render(*this, tag);
/* 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)
}
+Renderer::BoundTexture::BoundTexture():
+ unit(-1),
+ texture(0),
+ sampler(0),
+ replaced(-1)
+{ }
+
+
Renderer::State::State():
camera(0),
- texture(0),
- texturing(0),
+ texture_count(0),
lowest_effect_texunit(TexUnit::get_n_units()),
material(0),
lighting(0),