inline unsigned get_type_size(DataType t) { return t&0xFF; }
inline bool is_matrix(DataType t) { return t&0xC000; }
inline bool is_vector(DataType t) { return !is_matrix(t) && (t&0x3000); }
+inline bool is_image(DataType t) { return t&0x70000; }
GLenum get_gl_type(DataType);
DataType from_gl_type(GLenum);
i->location = glGetUniformLocation(id, i->name.c_str());
i->block = &default_block;
default_block.uniforms.push_back(&*i);
+
+ if(is_image(i->type) && i->location>=0)
+ glGetUniformiv(id, i->location, &i->binding);
}
default_block.layout_hash = compute_layout_hash(default_block.uniforms);
return i!=uniforms.end() && i->tag==tag && i->block->bind_point<0 ? i->location : -1;
}
+int Program::get_uniform_binding(Tag tag) const
+{
+ vector<UniformInfo>::const_iterator i = lower_bound_member(uniforms, tag, &UniformInfo::tag);
+ return i!=uniforms.end() && i->tag==tag ? i->binding : -1;
+}
+
const Program::AttributeInfo &Program::get_attribute_info(const string &name) const
{
vector<AttributeInfo>::const_iterator i = lower_bound_member(attributes, name, &AttributeInfo::name);
array_size(0),
array_stride(0),
matrix_stride(0),
- type(VOID)
+ type(VOID),
+ binding(-1)
{ }
unsigned matrix_stride;
DataType type;
Tag tag;
+ int binding;
UniformInfo();
};
const UniformInfo &get_uniform_info(Tag) const;
int get_uniform_location(const std::string &) const;
int get_uniform_location(Tag) const;
+ int get_uniform_binding(Tag) const;
const std::vector<AttributeInfo> &get_attributes() const { return attributes; }
const AttributeInfo &get_attribute_info(const std::string &) const;
int get_attribute_location(const std::string &) const;
linear_sampler(resources.get<Sampler>("_linear_clamp.samp")),
nearest_sampler(resources.get<Sampler>("_nearest_clamp.samp"))
{
- texturing.attach(2, occlude_target.get_target_texture(RENDER_COLOR), &linear_sampler);
-
unsigned seed = 1;
rotate_lookup.storage(RGBA8, 4, 4, 1);
unsigned char data[64];
}
rotate_lookup.image(0, data);
- texturing.attach(3, rotate_lookup, &nearest_sampler);
-
- shdata.uniform("source", 0);
- shdata.uniform("depth", 1);
- shdata.uniform("occlusion", 2);
- shdata.uniform("rotate", 3);
shdata.uniform("inverse_projection", Matrix());
set_n_samples(16);
void AmbientOcclusion::render(Renderer &renderer, const Texture2D &color, const Texture2D &depth)
{
- texturing.attach(0, color, &nearest_sampler);
- texturing.attach(1, depth, &nearest_sampler);
-
if(renderer.get_camera())
shdata.uniform("inverse_projection", invert(renderer.get_camera()->get_projection_matrix()));
Renderer::Push push(renderer);
- renderer.set_texturing(&texturing);
+ renderer.set_texture("source", &color, &nearest_sampler);
+ renderer.set_texture("depth", &depth, &nearest_sampler);
+ renderer.set_texture("occlusion", &occlude_target.get_target_texture(RENDER_COLOR), &linear_sampler);
+ renderer.set_texture("rotate", &rotate_lookup, &nearest_sampler);
renderer.set_shader_program(&occlude_shader, &shdata);
{
#include "programdata.h"
#include "rendertarget.h"
#include "texture2d.h"
-#include "texturing.h"
namespace Msp {
namespace GL {
private:
Texture2D rotate_lookup;
RenderTarget occlude_target;
- Texturing texturing;
const Program &occlude_shader;
const Program &combine_shader;
mutable ProgramData shdata;
for(unsigned i=0; i<2; ++i)
target[i] = new RenderTarget(w, h, (RENDER_COLOR,RGB16F));
- common_shdata.uniform("source", 0);
- common_shdata.uniform("blurred", 1);
-
- combine_texturing.attach(1, target[1]->get_target_texture(RENDER_COLOR), &linear_sampler);
-
set_radius(2.0f);
set_strength(0.2f);
}
{
BindRestore bind_fbo(target[i]->get_framebuffer());
Renderer::Push push2(renderer);
- renderer.set_texture(i ? &target[0]->get_target_texture(RENDER_COLOR) : &src, &nearest_sampler);
+ renderer.set_texture("source", (i ? &target[0]->get_target_texture(RENDER_COLOR) : &src), &nearest_sampler);
renderer.add_shader_data(blur_shdata[i]);
quad.draw(renderer);
}
- combine_texturing.attach(0, src, &nearest_sampler);
- renderer.set_texturing(&combine_texturing);
+ renderer.set_texture("source", &src, &nearest_sampler);
+ renderer.set_texture("blurred", &target[1]->get_target_texture(RENDER_COLOR), &linear_sampler);
renderer.set_shader_program(&combine_shader);
quad.draw(renderer);
}
#include "mesh.h"
#include "postprocessor.h"
#include "texture2d.h"
-#include "texturing.h"
#include "program.h"
#include "programdata.h"
#include "rendertarget.h"
const Mesh &quad;
const Sampler &nearest_sampler;
const Sampler &linear_sampler;
- Texturing combine_texturing;
public:
Bloom(Resources &, unsigned, unsigned);
linear_sampler(resources.get<Sampler>("_linear_clamp.samp")),
nearest_sampler(resources.get<Sampler>("_nearest_clamp.samp"))
{
- shdata.uniform("source", 0);
- shdata.uniform("curve", 1);
-
curve.storage(LUMINANCE8, 256, 1);
- texturing.attach(1, curve, &linear_sampler);
set_exposure_adjust(0.0f);
set_brightness_response(0.4f);
void ColorCurve::render(Renderer &renderer, const Texture2D &color_buf, const Texture2D &)
{
- texturing.attach(0, color_buf, &nearest_sampler);
-
Renderer::Push push(renderer);
renderer.set_shader_program(&shprog, &shdata);
- renderer.set_texturing(&texturing);
+ renderer.set_texture("source", &color_buf, &nearest_sampler);
+ renderer.set_texture("curve", &curve, &linear_sampler);
quad.draw(renderer);
}
#include "program.h"
#include "programdata.h"
#include "texture1d.h"
-#include "texturing.h"
namespace Msp {
namespace GL {
const Program &shprog;
ProgramData shdata;
Texture1D curve;
- Texturing texturing;
const Mesh &quad;
const Sampler &linear_sampler;
const Sampler &nearest_sampler;
Renderer::Push _push_rend(renderer);
- unsigned unit = renderer.allocate_effect_texunit();
- shdata.uniform("environment_map", static_cast<int>(unit));
- Bind _bind_sampler(sampler, unit);
- Bind _bind_env(env_tex, unit);
-
const Matrix &camera_matrix = renderer.get_camera()->get_object_matrix();
shdata.uniform("env_eye_matrix", camera_matrix.block<3, 3>(0, 0));
+ renderer.set_texture("environment_map", &env_tex, &sampler);
renderer.add_shader_data(shdata);
renderer.render(renderable, tag);
}
if(!enabled_passes.count(tag))
return renderer.render(renderable, tag);
- Renderer::Push _push_rend(renderer);
-
- unsigned unit = renderer.allocate_effect_texunit();
- int iunit = unit;
- shdata.uniform("shadow_map", iunit);
-
- Bind _bind_sampler(sampler, unit);
- Bind _bind_depth(depth_buf, unit);
-
if(const Camera *camera = renderer.get_camera())
/* Multiply by camera's object matrix to form a matrix that transforms
from eye space to shadow space. */
else
shdata.uniform("shd_eye_matrix", shadow_matrix);
+ Renderer::Push _push_rend(renderer);
+
+ renderer.set_texture("shadow_map", &depth_buf, &sampler);
renderer.add_shader_data(shdata);
renderer.render(renderable, tag);
}
namespace Msp {
namespace GL {
+const Tag BasicMaterial::texture_tags[] =
+{
+ Tag("diffuse_map"),
+ Tag("specular_map"),
+ Tag("shininess_map"),
+ Tag("normal_map"),
+ Tag("emission_map"),
+ Tag("reflectivity_map"),
+ Tag()
+};
+
BasicMaterial::BasicMaterial():
receive_shadows(false)
{
spec_values["use_shadow_map"] = receive_shadows;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void BasicMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
{
attach_texture_to(diffuse.texture, texturing, tex_shdata, "diffuse_map");
attach_texture_to(shininess.texture, texturing, tex_shdata, "shininess_map");
attach_texture_to(reflectivity.texture, texturing, tex_shdata, "reflectivity_map");
}
+#pragma GCC diagnostic pop
+
+const Texture *BasicMaterial::get_texture(Tag tag) const
+{
+ if(tag==texture_tags[0])
+ return diffuse.texture;
+ else if(tag==texture_tags[1])
+ return specular.texture;
+ else if(tag==texture_tags[2])
+ return shininess.texture;
+ else if(tag==texture_tags[3])
+ return normal.texture;
+ else if(tag==texture_tags[4])
+ return emission.texture;
+ else if(tag==texture_tags[5])
+ return reflectivity.texture;
+ else
+ return 0;
+}
void BasicMaterial::set_diffuse(const Color &color)
{
Property<float> reflectivity;
bool receive_shadows;
+ static const Tag texture_tags[];
+
public:
BasicMaterial();
virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
public:
- virtual void attach_textures_to(Texturing &, ProgramData &) const;
+ DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+
+ virtual const Tag *get_texture_tags() const { return texture_tags; }
+ virtual const Texture *get_texture(Tag) const;
void set_diffuse(const Color &);
void set_diffuse_map(const Texture *);
return shprog;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void Material::attach_texture_to(const Texture *tex, Texturing &texturing, ProgramData &tex_shdata, const string &name) const
{
if(!tex)
texturing.attach(unit, *tex, sampler);
tex_shdata.uniform(name, unit);
}
+#pragma GCC diagnostic pop
Material::MaterialRegistry &Material::get_material_registry()
{
const ProgramData &get_shader_data() const { return shdata; }
protected:
- void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
+ DEPRECATED void attach_texture_to(const Texture *, Texturing &, ProgramData &, const std::string &) const;
public:
- virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+ DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const = 0;
+
+ virtual const Tag *get_texture_tags() const = 0;
+ virtual const Texture *get_texture(Tag) const = 0;
+ const Sampler *get_sampler() const { return sampler; }
template<typename T>
static void register_type(const std::string &);
namespace Msp {
namespace GL {
+const Tag PbrMaterial::texture_tags[] =
+{
+ Tag("base_color_map"),
+ Tag("normal_map"),
+ Tag("metalness_map"),
+ Tag("roughness_map"),
+ Tag("occlusion_map"),
+ Tag("emission_map"),
+ Tag()
+};
+
PbrMaterial::PbrMaterial():
receive_shadows(false)
{
spec_values["use_shadow_map"] = receive_shadows;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void PbrMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
{
attach_texture_to(base_color.texture, texturing, tex_shdata, "base_color_map");
attach_texture_to(occlusion.texture, texturing, tex_shdata, "occlusion_map");
attach_texture_to(emission.texture, texturing, tex_shdata, "emission_map");
}
+#pragma GCC diagnostic pop
+
+const Texture *PbrMaterial::get_texture(Tag tag) const
+{
+ if(tag==texture_tags[0])
+ return base_color.texture;
+ else if(tag==texture_tags[1])
+ return normal.texture;
+ else if(tag==texture_tags[2])
+ return metalness.texture;
+ else if(tag==texture_tags[3])
+ return roughness.texture;
+ else if(tag==texture_tags[4])
+ return occlusion.texture;
+ else if(tag==texture_tags[5])
+ return emission.texture;
+ else
+ return 0;
+}
void PbrMaterial::set_base_color(const Color &color)
{
Property<Color> emission;
bool receive_shadows;
+ static const Tag texture_tags[];
+
public:
PbrMaterial();
virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
public:
- virtual void attach_textures_to(Texturing &, ProgramData &) const;
+ DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+
+ virtual const Tag *get_texture_tags() const { return texture_tags; }
+ virtual const Texture *get_texture(Tag) const;
void set_base_color(const Color &);
void set_base_color_map(const Texture *);
+#include <msp/core/algorithm.h>
#include <msp/datafile/collection.h>
#include <msp/io/print.h>
#include <msp/strings/format.h>
#include "error.h"
-#include "material.h"
#include "renderpass.h"
#include "program.h"
#include "programdata.h"
#include "texture.h"
#include "texture2d.h"
#include "texturing.h"
+#include "uniform.h"
using namespace std;
shprog_from_material(false),
shdata(0),
material(0),
- texturing(0),
back_faces(false)
{ }
-RenderPass::RenderPass(const RenderPass &other):
- shprog(other.shprog),
- shprog_from_material(other.shprog_from_material),
- shdata(other.shdata),
- uniform_slots(other.uniform_slots),
- material(other.material),
- material_slot(other.material_slot),
- texturing(other.texturing ? new Texturing(*other.texturing) : 0),
- tex_names(other.tex_names),
- back_faces(other.back_faces)
-{ }
-
-RenderPass &RenderPass::operator=(const RenderPass &other)
-{
- shprog = other.shprog;
- shprog_from_material = other.shprog_from_material;
- shdata = other.shdata;
- uniform_slots = other.uniform_slots;
- material = other.material;
- material_slot = other.material_slot;
- texturing = other.texturing ? new Texturing(*other.texturing) : 0;
- tex_names = other.tex_names;
- back_faces = other.back_faces;
- return *this;
-}
-
-RenderPass::~RenderPass()
-{
- delete texturing;
-}
-
void RenderPass::finalize_material(DataFile::Collection *coll)
{
maybe_create_material_shader(coll);
ensure_private_shader_data();
- if(!texturing)
- texturing = new Texturing;
- material->attach_textures_to(*texturing, *shdata);
+ const Tag *material_texture_tags = material->get_texture_tags();
+ for(const Tag *tag=material_texture_tags; tag->id; ++tag)
+ set_texture(*tag, material->get_texture(*tag), material->get_sampler());
}
void RenderPass::maybe_create_material_shader(DataFile::Collection *coll)
finalize_material(coll);
}
+void RenderPass::set_texture(Tag tag, const Texture *tex, const Sampler *samp)
+{
+ vector<TextureSlot>::iterator i = find_member(textures, tag, &TextureSlot::tag);
+ if(i==textures.end())
+ {
+ textures.push_back(TextureSlot(tag));
+ i = textures.end()-1;
+ }
+ i->texture = tex;
+ if(samp)
+ i->sampler = samp;
+}
+
+Tag RenderPass::get_texture_tag(const string &slot) const
+{
+ vector<TextureSlot>::const_iterator i = find_member(textures, slot, &TextureSlot::slot_name);
+ return (i!=textures.end() ? i->tag : Tag());
+}
+
void RenderPass::set_texture(unsigned index, const Texture *tex, const Sampler *samp)
{
- if(!texturing)
- texturing = new Texturing;
+ if(!shprog)
+ throw invalid_operation("RenderPass::set_texture");
+
+ const vector<Program::UniformInfo> &uniforms = shprog->get_uniforms();
+ for(vector<Program::UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+ if(is_image(i->type) && i->binding==static_cast<int>(index))
+ return set_texture(i->tag, tex, samp);
- texturing->attach(index, *tex, (samp ? samp : texturing->get_attached_sampler(index)));
+ if(shdata)
+ {
+ const vector<Tag> &tags = shdata->get_uniform_tags();
+ for(vector<Tag>::const_iterator i=tags.begin(); i!=tags.end(); ++i)
+ {
+ vector<Program::UniformInfo>::const_iterator j = find_member(uniforms, *i, &Program::UniformInfo::tag);
+ if(j==uniforms.end() || !is_image(j->type))
+ continue;
+ if(const Uniform1i *uni1i = dynamic_cast<const Uniform1i *>(shdata->find_uniform(*i)))
+ if(uni1i->get()==static_cast<int>(index))
+ return set_texture(*i, tex, samp);
+ }
+ }
}
int RenderPass::get_texture_index(const string &n) const
{
- map<string, unsigned>::const_iterator i = tex_names.find(n);
- if(i==tex_names.end())
- return -1;
- return i->second;
+ vector<TextureSlot>::const_iterator i = find_member(textures, n, &TextureSlot::slot_name);
+ return (shprog && i!=textures.end() ? shprog->get_uniform_binding(i->tag) : -1);
}
void RenderPass::apply(Renderer &renderer) const
{
- renderer.set_texturing(texturing);
+ for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
+ renderer.set_texture(i->tag, i->texture, i->sampler);
renderer.set_material(material.get());
renderer.set_shader_program(shprog.get(), shdata.get());
renderer.set_reverse_winding(back_faces);
add("material", &Loader::material);
add("material_slot", &RenderPass::material_slot);
add("back_faces",&RenderPass::back_faces);
- add("texunit", &Loader::texunit);
- add("texunit", &Loader::texunit_auto);
- add("texunit", &Loader::texunit_named);
+ add("texture", &Loader::texture);
add("uniforms", &Loader::uniforms);
add("uniform_slot", &Loader::uniform_slot);
add("uniform_slot", &Loader::uniform_slot2);
+
+ // Deprecated
+ add("texunit", &Loader::texunit);
+ add("texunit", &Loader::texture);
+ add("texunit", &Loader::texunit_named);
}
// Temporary compatibility feature
obj.finalize_material(coll);
}
-void RenderPass::Loader::texunit(unsigned i)
+void RenderPass::Loader::texture(const string &n)
{
- if(!obj.texturing)
- obj.texturing = new Texturing;
- TextureLoader ldr(*obj.texturing, i, coll);
+ vector<TextureSlot>::iterator i = find_member(obj.textures, Tag(n), &TextureSlot::tag);
+ if(i==obj.textures.end())
+ {
+ obj.textures.push_back(TextureSlot(n));
+ i = obj.textures.end()-1;
+ }
+ TextureSlot::Loader ldr(*i, n, coll);
load_sub_with(ldr);
}
-void RenderPass::Loader::texunit_auto(const string &n)
+void RenderPass::Loader::texunit(unsigned)
{
- if(!obj.texturing)
- obj.texturing = new Texturing;
- int i = obj.texturing->find_free_unit(n);
- if(i<0)
- throw runtime_error("no free texunit");
- texunit_named(i, n);
+ IO::print(IO::cerr, "Warning: specifying textures by unit number is deprecated and may not produce expected results");
+ string name;
+ if(obj.shprog)
+ {
+ const vector<Program::UniformInfo> &uniforms = obj.shprog->get_uniforms();
+ for(vector<Program::UniformInfo>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+ if(is_image(i->type) && i->binding>=0)
+ {
+ if(!name.empty())
+ {
+ name.clear();
+ break;
+ }
+ name = i->name;
+ }
+ }
+
+ if(name.empty())
+ throw runtime_error("Could not determine name for texture");
+
+ texture(name);
}
-void RenderPass::Loader::texunit_named(unsigned i, const string &n)
+void RenderPass::Loader::texunit_named(unsigned, const string &n)
{
- texunit(i);
- obj.tex_names[n] = i;
- obj.ensure_private_shader_data();
- obj.shdata->uniform(n, static_cast<int>(i));
+ texture(n);
}
void RenderPass::Loader::uniforms()
}
-RenderPass::TextureLoader::TextureLoader(Texturing &t, unsigned i, Collection *c):
- DataFile::CollectionObjectLoader<Texturing>(t, c),
- index(i),
- tex(0),
- samp(0)
-{
- add("sampler", &TextureLoader::sampler);
- add("texture", &TextureLoader::texture);
-}
-
-void RenderPass::TextureLoader::finish()
-{
- if(tex)
- obj.attach(index, *tex, samp);
- else if(samp)
- obj.attach(index, *samp);
-}
-
-void RenderPass::TextureLoader::sampler(const string &name)
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &ts, const string &an, Collection *c):
+ CollectionObjectLoader<TextureSlot>(ts, c),
+ auto_slot_name(an)
{
- samp = &get_collection().get<Sampler>(name);
+ add("sampler", &TextureSlot::sampler);
+ add("slot", &Loader::slot_auto);
+ add("slot", &TextureSlot::slot_name);
+ add("texture", &TextureSlot::texture);
}
-void RenderPass::TextureLoader::texture(const string &name)
+void RenderPass::TextureSlot::Loader::slot_auto()
{
- tex = &get_collection().get<Texture>(name);
+ obj.slot_name = auto_slot_name;
}
} // namespace GL
#include <msp/core/refptr.h>
#include <msp/datafile/objectloader.h>
+#include "material.h"
namespace Msp {
namespace GL {
-class Material;
class Program;
class ProgramData;
class Renderer;
void material_inline();
void material(const std::string &);
void shader(const std::string &);
+ void texture(const std::string &);
void texunit(unsigned);
- void texunit_auto(const std::string &);
void texunit_named(unsigned, const std::string &);
void uniforms();
void uniform_slot(const std::string &);
};
private:
- struct TextureLoader: public DataFile::CollectionObjectLoader<Texturing>
+ struct TextureSlot
{
- private:
- unsigned index;
- const Texture *tex;
- const Sampler *samp;
+ class Loader: public DataFile::CollectionObjectLoader<TextureSlot>
+ {
+ private:
+ std::string auto_slot_name;
- public:
- TextureLoader(Texturing &, unsigned, Collection *);
- private:
- virtual void finish();
+ public:
+ Loader(TextureSlot &, const std::string &, Collection *);
- void sampler(const std::string &);
- void texture(const std::string &);
+ private:
+ void slot_auto();
+ };
+
+ Tag tag;
+ std::string slot_name;
+ const Texture *texture;
+ const Sampler *sampler;
+
+ TextureSlot(Tag t): tag(t), texture(0), sampler(0) { }
};
RefPtr<const Program> shprog;
std::map<Tag, Tag> uniform_slots;
RefPtr<const Material> material;
std::string material_slot;
- Texturing *texturing;
- std::map<std::string, unsigned> tex_names;
+ std::vector<TextureSlot> textures;
bool back_faces;
public:
RenderPass();
- RenderPass(const RenderPass &);
- RenderPass &operator=(const RenderPass &);
- ~RenderPass();
private:
void finalize_material(DataFile::Collection *);
void set_material(const Material *, DataFile::Collection * = 0);
const Material *get_material() const { return material.get(); }
const std::string &get_material_slot_name() const { return material_slot; }
- void set_texture(unsigned, const Texture *, const Sampler * = 0);
- const Texturing *get_texturing() const { return texturing; }
- int get_texture_index(const std::string &) const;
+ void set_texture(Tag, const Texture *, const Sampler * = 0);
+ Tag get_texture_tag(const std::string &) const;
+ DEPRECATED void set_texture(unsigned, const Texture *, const Sampler * = 0);
+ DEPRECATED const Texturing *get_texturing() const { return 0; }
+ DEPRECATED int get_texture_index(const std::string &) const;
void set_back_faces(bool);
bool get_back_faces() const { return back_faces; }
bool replaced = false;
for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i)
{
- int index = i->second.get_texture_index(slot);
- if(index>=0)
+ Tag tag = i->second.get_texture_tag(slot);
+ if(tag.id)
{
- i->second.set_texture(index, &tex);
+ i->second.set_texture(tag, &tex);
replaced = true;
}
}
namespace Msp {
namespace GL {
+const Tag UnlitMaterial::texture_tags[] =
+{
+ Tag("color_tex"),
+ Tag()
+};
+
UnlitMaterial::UnlitMaterial():
texture(0),
vertex_color(false)
spec_values["use_vertex_color"] = vertex_color;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void UnlitMaterial::attach_textures_to(Texturing &texturing, ProgramData &tex_shdata) const
{
attach_texture_to(texture, texturing, tex_shdata, "color_tex");
}
+#pragma GCC diagnostic pop
+
+const Texture *UnlitMaterial::get_texture(Tag tag) const
+{
+ if(tag==texture_tags[0])
+ return texture;
+ else
+ return 0;
+}
void UnlitMaterial::set_texture(const Texture *tex)
{
Color color;
bool vertex_color;
+ static const Tag texture_tags[];
+
public:
UnlitMaterial();
virtual void fill_program_info(std::string &, std::map<std::string, int> &) const;
public:
- virtual void attach_textures_to(Texturing &, ProgramData &) const;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ DEPRECATED virtual void attach_textures_to(Texturing &, ProgramData &) const;
+#pragma GCC diagnostic pop
+
+ virtual const Tag *get_texture_tags() const { return texture_tags; }
+ virtual const Texture *get_texture(Tag) const;
void set_texture(const Texture *);
void set_color(const Color &);
#endif
{
if(tied_program)
- tied_program->get_uniform_info(tag);
+ {
+ const Program::UniformInfo &info = tied_program->get_uniform_info(tag);
+ if(is_image(info.type))
+ throw invalid_operation("ProgramData::uniform");
+ }
return true;
}
#ifdef DEBUG
{
const UInt8 *indices = block.get_uniform_indices();
for(unsigned i=0; i<info.uniforms.size(); ++i)
- if(indices[i]!=0xFF)
+ {
+ if(is_image(info.uniforms[i]->type))
+ ; // Temporarily ignore deprecated use of sampler uniforms in ProgramData
+ else if(indices[i]!=0xFF)
block.block->attach(*info.uniforms[i], *uniforms[indices[i]].value);
+ }
}
void ProgramData::apply() const
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();
/* 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),
};
private:
+ struct BoundTexture
+ {
+ Tag tag;
+ mutable int unit;
+ const Texture *texture;
+ const Sampler *sampler;
+ int replaced;
+
+ BoundTexture();
+ };
+
struct State
{
const Camera *camera;
Matrix modelview_matrix;
- const Texture *texture;
- const Sampler *sampler;
- const Texturing *texturing;
+ unsigned texture_count;
unsigned lowest_effect_texunit;
const Material *material;
const Lighting *lighting;
unsigned char changed;
std::vector<State> state_stack;
State *state;
+ std::vector<BoundTexture> texture_stack;
ProgramData standard_shdata;
std::vector<const ProgramData *> shdata_stack;
std::set<const Renderable *> excluded;
/** Returns the current modelview matrix. */
const Matrix &get_matrix() const { return state->modelview_matrix; }
- void set_texture(const Texture *, const Sampler * = 0);
- void set_texturing(const Texturing *);
- unsigned allocate_effect_texunit();
+ void set_texture(Tag, const Texture *, const Sampler * = 0);
+private:
+ void set_texture(Tag, int, const Texture *, const Sampler *);
+ void flush_textures();
+public:
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ DEPRECATED void set_texture(const Texture *, const Sampler * = 0);
+ DEPRECATED void set_texturing(const Texturing *);
+ DEPRECATED unsigned allocate_effect_texunit();
+#pragma GCC diagnostic pop
void set_material(const Material *);
void set_lighting(const Lighting *);
using namespace std;
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
namespace Msp {
namespace GL {
class Texture;
-class Texturing: public Bindable<Texturing>
+class DEPRECATED Texturing: public Bindable<Texturing>
{
private:
struct Attachment