From 78840e775c62c1b6e3f550bf8be1f0b828df91aa Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 31 Jan 2021 02:55:49 +0200 Subject: [PATCH] Move texture sampler state to a separate object First step in supporting sampler objects --- source/ambientocclusion.cpp | 2 +- source/colorcurve.cpp | 5 +- source/environmentmap.cpp | 5 +- source/rendertarget.cpp | 7 +- source/resources.cpp | 9 +- source/sampler.cpp | 273 ++++++++++++++++++++++++++++++++++++ source/sampler.h | 164 ++++++++++++++++++++++ source/shadowmap.cpp | 8 +- source/texture.cpp | 123 ++++------------ source/texture.h | 105 ++++---------- source/texture2d.cpp | 1 + 11 files changed, 507 insertions(+), 195 deletions(-) create mode 100644 source/sampler.cpp create mode 100644 source/sampler.h diff --git a/source/ambientocclusion.cpp b/source/ambientocclusion.cpp index 3fbaf81a..8826964a 100644 --- a/source/ambientocclusion.cpp +++ b/source/ambientocclusion.cpp @@ -22,7 +22,7 @@ AmbientOcclusion::AmbientOcclusion(unsigned w, unsigned h, float): unsigned seed = 1; rotate_lookup.storage(RGBA, 4, 4, 1); - rotate_lookup.set_filter(NEAREST); + rotate_lookup.get_default_sampler().set_filter(NEAREST); unsigned char data[64]; for(unsigned i=0; i<16; ++i) { diff --git a/source/colorcurve.cpp b/source/colorcurve.cpp index f11b83ae..8983df2b 100644 --- a/source/colorcurve.cpp +++ b/source/colorcurve.cpp @@ -19,8 +19,9 @@ ColorCurve::ColorCurve(): shdata.uniform("curve", 1); curve.storage(LUMINANCE, 256, 1); - curve.set_min_filter(LINEAR); - curve.set_wrap(CLAMP_TO_EDGE); + Sampler &sampler = curve.get_default_sampler(); + sampler.set_min_filter(LINEAR); + sampler.set_wrap(CLAMP_TO_EDGE); texturing.attach(1, curve); set_exposure_adjust(0.0f); diff --git a/source/environmentmap.cpp b/source/environmentmap.cpp index 68e5051e..ac68ff99 100644 --- a/source/environmentmap.cpp +++ b/source/environmentmap.cpp @@ -18,8 +18,9 @@ EnvironmentMap::EnvironmentMap(unsigned s, Renderable &r, Renderable &e): update_delay(0) { env_tex.storage(RGB, size, 1); - env_tex.set_wrap(CLAMP_TO_EDGE); - env_tex.set_min_filter(LINEAR); + Sampler &env_samp = env_tex.get_default_sampler(); + env_samp.set_wrap(CLAMP_TO_EDGE); + env_samp.set_min_filter(LINEAR); depth_buf.storage(DEPTH_COMPONENT, size, size); for(unsigned i=0; i<6; ++i) { diff --git a/source/rendertarget.cpp b/source/rendertarget.cpp index ea8bb0c8..74b4f322 100644 --- a/source/rendertarget.cpp +++ b/source/rendertarget.cpp @@ -139,8 +139,9 @@ void RenderTarget::init(unsigned w, unsigned h, unsigned s, const RenderTargetFo { tgt.texture = new Texture2D; tgt.texture->storage(pf, width, height, 1); - tgt.texture->set_filter(NEAREST); - tgt.texture->set_wrap(CLAMP_TO_EDGE); + Sampler &sampler = tgt.texture->get_default_sampler(); + sampler.set_filter(NEAREST); + sampler.set_wrap(CLAMP_TO_EDGE); fbo.attach(att, *tgt.texture); } buffers.push_back(tgt); @@ -165,7 +166,7 @@ void RenderTarget::set_texture_filter(TextureFilter filt) if(!samples) { for(vector::iterator i=buffers.begin(); i!=buffers.end(); ++i) - i->texture->set_filter(filt); + i->texture->get_default_sampler().set_filter(filt); } } diff --git a/source/resources.cpp b/source/resources.cpp index 8aecb933..dd9a3c68 100644 --- a/source/resources.cpp +++ b/source/resources.cpp @@ -132,15 +132,16 @@ Texture2D *Resources::create_texture2d(const string &name) RefPtr tex = new Texture2D(resource_manager); + Sampler &samp = tex->get_default_sampler(); if(is_mipmapped(default_tex_filter)) { tex->set_auto_generate_mipmap(true); - tex->set_mag_filter(LINEAR); + samp.set_mag_filter(LINEAR); } else - tex->set_mag_filter(default_tex_filter); - tex->set_min_filter(default_tex_filter); - tex->set_max_anisotropy(default_tex_anisotropy); + samp.set_mag_filter(default_tex_filter); + samp.set_min_filter(default_tex_filter); + samp.set_max_anisotropy(default_tex_anisotropy); if(resource_manager) resource_manager->set_resource_location(*tex, *this, name); diff --git a/source/sampler.cpp b/source/sampler.cpp new file mode 100644 index 00000000..9476ffe9 --- /dev/null +++ b/source/sampler.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "sampler.h" +#include "texture.h" +#include "texunit.h" + +using namespace std; + +namespace Msp { +namespace GL { + +Sampler::Sampler(const Texture &tex): + id(0), + owner(&tex) +{ + if(this!=&tex.get_default_sampler()) + throw invalid_argument("Sampler::Sampler"); + + init(); +} + +void Sampler::init() +{ + min_filter = NEAREST_MIPMAP_LINEAR; + mag_filter = LINEAR; + max_anisotropy = 1.0f; + wrap_s = REPEAT; + wrap_t = REPEAT; + wrap_r = REPEAT; + compare = false; + cmp_func = LEQUAL; + dirty_params = 0; +} + +void Sampler::update_parameter(int mask) const +{ + if(!owner->get_id() || (!ARB_direct_state_access && TexUnit::current().get_texture()!=owner)) + { + TexUnit *unit = TexUnit::find_unit(owner); + if(!unit) + { + dirty_params |= mask; + return; + } + + unit->bind(); + } + + if(mask&MIN_FILTER) + set_parameter_i(GL_TEXTURE_MIN_FILTER, min_filter); + if(mask&MAG_FILTER) + set_parameter_i(GL_TEXTURE_MAG_FILTER, mag_filter); + if(mask&MAX_ANISOTROPY) + set_parameter_f(GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy); + if(mask&WRAP_S) + set_parameter_i(GL_TEXTURE_WRAP_S, wrap_s); + if(mask&WRAP_T) + set_parameter_i(GL_TEXTURE_WRAP_T, wrap_t); + if(mask&WRAP_R) + set_parameter_i(GL_TEXTURE_WRAP_R, wrap_r); + if(mask&COMPARE) + { + set_parameter_i(GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE)); + if(compare) + set_parameter_i(GL_TEXTURE_COMPARE_FUNC, cmp_func); + } +} + +void Sampler::set_parameter_i(unsigned param, int value) const +{ + if(ARB_direct_state_access) + glTextureParameteri(owner->get_id(), param, value); + else + glTexParameteri(owner->get_target(), param, value); +} + +void Sampler::set_parameter_f(unsigned param, float value) const +{ + if(ARB_direct_state_access) + glTextureParameterf(owner->get_id(), param, value); + else + glTexParameterf(owner->get_target(), param, value); +} + +void Sampler::set_min_filter(TextureFilter f) +{ + min_filter = f; + update_parameter(MIN_FILTER); +} + +void Sampler::set_mag_filter(TextureFilter f) +{ + mag_filter = f; + update_parameter(MAG_FILTER); +} + +void Sampler::set_filter(TextureFilter f) +{ + set_min_filter(f); + set_mag_filter(f==NEAREST ? NEAREST : LINEAR); +} + +void Sampler::set_max_anisotropy(float a) +{ + if(a<1.0f) + throw invalid_argument("Sampler::set_max_anisotropy"); + else if(a>1.0f) + static Require _req(EXT_texture_filter_anisotropic); + max_anisotropy = a; + if(EXT_texture_filter_anisotropic) + update_parameter(MAX_ANISOTROPY); +} + +void Sampler::set_wrap(TextureWrap w) +{ + set_wrap_s(w); + set_wrap_t(w); + if(EXT_texture3D) + set_wrap_r(w); +} + +void Sampler::set_wrap_s(TextureWrap w) +{ + wrap_s = w; + update_parameter(WRAP_S); +} + +void Sampler::set_wrap_t(TextureWrap w) +{ + wrap_t = w; + update_parameter(WRAP_T); +} + +void Sampler::set_wrap_r(TextureWrap w) +{ + static Require _req(EXT_texture3D); + wrap_r = w; + update_parameter(WRAP_R); +} + +void Sampler::disable_compare() +{ + compare = false; + update_parameter(COMPARE); +} + +void Sampler::set_compare(Predicate f) +{ + static Require _req(ARB_shadow); + compare = true; + cmp_func = f; + update_parameter(COMPARE); +} + +void Sampler::bind_to(unsigned i) const +{ + TexUnit &unit = TexUnit::get_unit(i); + if(owner!=unit.get_texture()) + throw invalid_operation("Sampler::bind_to"); + + if(dirty_params) + { + update_parameter(dirty_params); + dirty_params = 0; + } +} + +void Sampler::unload() +{ + // TODO check which params actually need refreshing + if(!owner->get_id()) + dirty_params = -1; +} + + +Sampler::Loader::Loader(Sampler &s): + DataFile::ObjectLoader(s) +{ + add("filter", &Loader::filter); + add("mag_filter", &Loader::mag_filter); + add("max_anisotropy", &Loader::max_anisotropy); + add("min_filter", &Loader::min_filter); + add("wrap", &Loader::wrap); + add("wrap_r", &Loader::wrap_r); + add("wrap_s", &Loader::wrap_s); + add("wrap_t", &Loader::wrap_t); +} + +void Sampler::Loader::filter(TextureFilter f) +{ + obj.set_filter(f); +} + +void Sampler::Loader::mag_filter(TextureFilter f) +{ + obj.set_mag_filter(f); +} + +void Sampler::Loader::max_anisotropy(float a) +{ + obj.set_max_anisotropy(a); +} + +void Sampler::Loader::min_filter(TextureFilter f) +{ + obj.set_min_filter(f); +} + +void Sampler::Loader::wrap(TextureWrap w) +{ + obj.set_wrap(w); +} + +void Sampler::Loader::wrap_r(TextureWrap w) +{ + obj.set_wrap_r(w); +} + +void Sampler::Loader::wrap_s(TextureWrap w) +{ + obj.set_wrap_s(w); +} + +void Sampler::Loader::wrap_t(TextureWrap w) +{ + obj.set_wrap_t(w); +} + + +bool is_mipmapped(TextureFilter filter) +{ + return (filter==NEAREST_MIPMAP_NEAREST || filter==NEAREST_MIPMAP_LINEAR || + filter==LINEAR_MIPMAP_NEAREST || filter==LINEAR_MIPMAP_LINEAR); +} + +void operator>>(const LexicalConverter &c, TextureFilter &tf) +{ + if(c.get()=="NEAREST") + tf = NEAREST; + else if(c.get()=="LINEAR") + tf = LINEAR; + else if(c.get()=="NEAREST_MIPMAP_NEAREST") + tf = NEAREST_MIPMAP_NEAREST; + else if(c.get()=="NEAREST_MIPMAP_LINEAR") + tf = NEAREST_MIPMAP_LINEAR; + else if(c.get()=="LINEAR_MIPMAP_NEAREST") + tf = LINEAR_MIPMAP_NEAREST; + else if(c.get()=="LINEAR_MIPMAP_LINEAR") + tf = LINEAR_MIPMAP_LINEAR; + else + throw lexical_error(format("conversion of '%s' to TextureFilter", c.get())); +} + +void operator>>(const LexicalConverter &c, TextureWrap &tw) +{ + if(c.get()=="REPEAT") + tw = REPEAT; + else if(c.get()=="CLAMP_TO_EDGE") + tw = CLAMP_TO_EDGE; + else if(c.get()=="MIRRORED_REPEAT") + tw = MIRRORED_REPEAT; + else + throw lexical_error(format("conversion of '%s' to TextureWrap", c.get())); +} + + +} // namespace GL +} // namespace Msp diff --git a/source/sampler.h b/source/sampler.h new file mode 100644 index 00000000..255d1da4 --- /dev/null +++ b/source/sampler.h @@ -0,0 +1,164 @@ +#ifndef MSP_GL_SAMPLER_H_ +#define MSP_GL_SAMPLER_H_ + +#include +#include "gl.h" +#include "predicate.h" + +namespace Msp { +namespace GL { + +enum TextureFilter +{ + /// No filtering + NEAREST = GL_NEAREST, + + /// Bilinear filtering + LINEAR = GL_LINEAR, + + /// Mipmapping without filtering + NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, + + /// Linear filtering between two mipmap levels + NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, + + /// Bilinear filtering on the closest mipmap level + LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, + + /// Trilinear filtering between two mipmap levels + LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR +}; + + +enum TextureWrap +{ + /// Tile the texture infinitely + REPEAT = GL_REPEAT, + + /// Extend the texels at the edge of the texture to infinity + CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, + + /// Tile the texture, with every other repetition mirrored + MIRRORED_REPEAT = GL_MIRRORED_REPEAT +}; + +class Texture; + + +/** +Samplers are used to access texture data in shaders. To use a sampler with a +texture, bind it to the same texture unit. Each texture has a default sampler +which is used if no external sampler is bound. + +A texture is generally rendered at a size that's either smaller or larger than +its native size, so that the texture coordinates do not exactly correspond to +the texels of the texture. The kind of filtering used, if any, is determined +by the minification and magnification filter parameters. The default is LINEAR +for magnification and NEAREST_MIPMAP_LINEAR for minification. + +If texture coordinates fall outside of the principal range of the texture, +wrapping is applied. The default for all directions is REPEAT. +*/ +class Sampler +{ +public: + class Loader: public DataFile::ObjectLoader + { + public: + Loader(Sampler &); + private: + void init(); + + void filter(TextureFilter); + void mag_filter(TextureFilter); + void max_anisotropy(float); + void min_filter(TextureFilter); + void wrap(TextureWrap); + void wrap_r(TextureWrap); + void wrap_s(TextureWrap); + void wrap_t(TextureWrap); + }; + +private: + enum ParameterMask + { + MIN_FILTER = 1, + MAG_FILTER = 2, + MAX_ANISOTROPY = 4, + WRAP_S = 8, + WRAP_T = 16, + WRAP_R = 32, + COMPARE = 64 + }; + + unsigned id; + const Texture *owner; + TextureFilter min_filter; + TextureFilter mag_filter; + float max_anisotropy; + TextureWrap wrap_s; + TextureWrap wrap_t; + TextureWrap wrap_r; + bool compare; + Predicate cmp_func; + mutable int dirty_params; + +public: + Sampler(); + Sampler(const Texture &); +private: + void init(); + + void update_parameter(int) const; + void set_parameter_i(unsigned, int) const; + void set_parameter_f(unsigned, float) const; + +public: + void set_min_filter(TextureFilter); + void set_mag_filter(TextureFilter); + + /** Sets filter for both minification and magnification. If a mipmapping + filter is specified, LINEAR is used for magnification. */ + void set_filter(TextureFilter); + + TextureFilter get_min_filter() const { return min_filter; } + TextureFilter get_mag_filter() const { return mag_filter; } + + void set_max_anisotropy(float); + float get_max_anisotropy() const { return max_anisotropy; } + + /** Sets the wrapping mode for all coordinates. */ + void set_wrap(TextureWrap); + + void set_wrap_s(TextureWrap); + void set_wrap_t(TextureWrap); + void set_wrap_r(TextureWrap); + + /** Disables depth comparison. */ + void disable_compare(); + + /** Enables depth comparison and sets the compare function. Only has an + effect when used with a depth texture. When depth comparison is enabled, + the third component of the texture coordinate is compared against the texel + value, and the result is returned as the texture sample.*/ + void set_compare(Predicate); + + bool is_compare_enabled() const { return compare; } + Predicate get_compare_function() const { return cmp_func; } + + void bind() const { bind_to(0); } + void bind_to(unsigned) const; + + void unload(); +}; + + +bool is_mipmapped(TextureFilter); + +void operator>>(const LexicalConverter &, TextureFilter &); +void operator>>(const LexicalConverter &, TextureWrap &); + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/shadowmap.cpp b/source/shadowmap.cpp index 0e32210f..5d658807 100644 --- a/source/shadowmap.cpp +++ b/source/shadowmap.cpp @@ -20,10 +20,10 @@ ShadowMap::ShadowMap(unsigned s, Renderable &r, const Light &l): depth_bias(4), rendered(false) { - depth_buf.set_min_filter(LINEAR); - depth_buf.set_compare_enabled(true); - depth_buf.set_compare_func(LEQUAL); - depth_buf.set_wrap(CLAMP_TO_EDGE); + Sampler &depth_samp = depth_buf.get_default_sampler(); + depth_samp.set_min_filter(LINEAR); + depth_samp.set_compare(LEQUAL); + depth_samp.set_wrap(CLAMP_TO_EDGE); depth_buf.storage(DEPTH_COMPONENT, size, size, 1); fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0); fbo.require_complete(); diff --git a/source/texture.cpp b/source/texture.cpp index b8c14792..7983cfb5 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -1,11 +1,7 @@ #include -#include #include #include -#include -#include #include -#include #include "bindable.h" #include "error.h" #include "resourcemanager.h" @@ -18,38 +14,6 @@ using namespace std; namespace Msp { namespace GL { -void operator>>(const LexicalConverter &c, TextureFilter &tf) -{ - if(c.get()=="NEAREST") - tf = NEAREST; - else if(c.get()=="LINEAR") - tf = LINEAR; - else if(c.get()=="NEAREST_MIPMAP_NEAREST") - tf = NEAREST_MIPMAP_NEAREST; - else if(c.get()=="NEAREST_MIPMAP_LINEAR") - tf = NEAREST_MIPMAP_LINEAR; - else if(c.get()=="LINEAR_MIPMAP_NEAREST") - tf = LINEAR_MIPMAP_NEAREST; - else if(c.get()=="LINEAR_MIPMAP_LINEAR") - tf = LINEAR_MIPMAP_LINEAR; - else - throw lexical_error(format("conversion of '%s' to TextureFilter", c.get())); -} - - -void operator>>(const LexicalConverter &c, TextureWrap &tw) -{ - if(c.get()=="REPEAT") - tw = REPEAT; - else if(c.get()=="CLAMP_TO_EDGE") - tw = CLAMP_TO_EDGE; - else if(c.get()=="MIRRORED_REPEAT") - tw = MIRRORED_REPEAT; - else - throw lexical_error(format("conversion of '%s' to TextureWrap", c.get())); -} - - int Texture::swizzle_orders[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, @@ -61,16 +25,9 @@ Texture::Texture(GLenum t, ResourceManager *m): id(0), target(t), ifmt(RGB), - min_filter(NEAREST_MIPMAP_LINEAR), - mag_filter(LINEAR), - max_anisotropy(1.0f), - wrap_s(REPEAT), - wrap_t(REPEAT), - wrap_r(REPEAT), auto_gen_mipmap(false), - compare(false), - cmp_func(LEQUAL), - dirty_params(0) + dirty_params(0), + default_sampler(*this) { if(m) set_manager(m); @@ -149,22 +106,6 @@ void Texture::update_parameter(int mask) const unit->bind(); } - if(mask&MIN_FILTER) - set_parameter_i(GL_TEXTURE_MIN_FILTER, min_filter); - if(mask&MAG_FILTER) - set_parameter_i(GL_TEXTURE_MAG_FILTER, mag_filter); - if(mask&MAX_ANISOTROPY) - set_parameter_f(GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy); - if(mask&WRAP_S) - set_parameter_i(GL_TEXTURE_WRAP_S, wrap_s); - if(mask&WRAP_T) - set_parameter_i(GL_TEXTURE_WRAP_T, wrap_t); - if(mask&WRAP_R) - set_parameter_i(GL_TEXTURE_WRAP_R, wrap_r); - if(mask&COMPARE) - set_parameter_i(GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE)); - if(mask&COMPARE_FUNC) - set_parameter_i(GL_TEXTURE_COMPARE_FUNC, cmp_func); if(mask&FORMAT_SWIZZLE) { if(get_gl_api()==OPENGL_ES2) @@ -202,58 +143,42 @@ void Texture::set_parameter_f(GLenum param, float value) const void Texture::set_min_filter(TextureFilter f) { - min_filter = f; - update_parameter(MIN_FILTER); + default_sampler.set_min_filter(f); } void Texture::set_mag_filter(TextureFilter f) { - mag_filter = f; - update_parameter(MAG_FILTER); + default_sampler.set_mag_filter(f); } void Texture::set_filter(TextureFilter f) { - set_min_filter(f); - set_mag_filter(f==NEAREST ? NEAREST : LINEAR); + default_sampler.set_filter(f); } void Texture::set_max_anisotropy(float a) { - if(a<1.0f) - throw invalid_argument("Texture::set_max_anisotropy"); - else if(a>1.0f) - static Require _req(EXT_texture_filter_anisotropic); - max_anisotropy = a; - if(EXT_texture_filter_anisotropic) - update_parameter(MAX_ANISOTROPY); + default_sampler.set_max_anisotropy(a); } void Texture::set_wrap(TextureWrap w) { - set_wrap_s(w); - set_wrap_t(w); - if(EXT_texture3D) - set_wrap_r(w); + default_sampler.set_wrap(w); } void Texture::set_wrap_s(TextureWrap w) { - wrap_s = w; - update_parameter(WRAP_S); + default_sampler.set_wrap_s(w); } void Texture::set_wrap_t(TextureWrap w) { - wrap_t = w; - update_parameter(WRAP_T); + default_sampler.set_wrap_t(w); } void Texture::set_wrap_r(TextureWrap w) { - static Require _req(EXT_texture3D); - wrap_r = w; - update_parameter(WRAP_R); + default_sampler.set_wrap_r(w); } bool Texture::can_generate_mipmap() @@ -286,16 +211,14 @@ void Texture::set_auto_generate_mipmap(bool gm) void Texture::set_compare_enabled(bool c) { if(c) - static Require _req(ARB_shadow); - compare = c; - update_parameter(COMPARE); + default_sampler.set_compare(default_sampler.get_compare_function()); + else + default_sampler.disable_compare(); } void Texture::set_compare_func(Predicate f) { - static Require _req(ARB_shadow); - cmp_func = f; - update_parameter(COMPARE_FUNC); + default_sampler.set_compare(f); } void Texture::load_image(const string &fn, bool srgb) @@ -348,6 +271,8 @@ void Texture::bind_to(unsigned i) const update_parameter(dirty_params); dirty_params = 0; } + + default_sampler.bind_to(i); } } @@ -401,6 +326,7 @@ void Texture::Loader::init() add("max_anisotropy", &Loader::max_anisotropy); add("min_filter", &Loader::min_filter); add("mipmap_levels", &Loader::mipmap_levels); + add("sampler", &Loader::sampler); add("wrap", &Loader::wrap); add("wrap_r", &Loader::wrap_r); add("wrap_s", &Loader::wrap_s); @@ -412,6 +338,8 @@ unsigned Texture::Loader::get_levels() const return (is_mipmapped(obj.default_sampler.get_min_filter()) ? levels : 1); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" void Texture::Loader::external_image(const string &fn) { Graphics::Image img; @@ -462,6 +390,11 @@ void Texture::Loader::mipmap_levels(unsigned l) levels = l; } +void Texture::Loader::sampler() +{ + load_sub(obj.default_sampler); +} + void Texture::Loader::wrap(TextureWrap w) { obj.set_wrap(w); @@ -481,13 +414,7 @@ void Texture::Loader::wrap_t(TextureWrap w) { obj.set_wrap_t(w); } - - -bool is_mipmapped(TextureFilter filter) -{ - return (filter==NEAREST_MIPMAP_NEAREST || filter==NEAREST_MIPMAP_LINEAR || - filter==LINEAR_MIPMAP_NEAREST || filter==LINEAR_MIPMAP_LINEAR); -} +#pragma GCC diagnostic pop } // namespace GL } // namespace Msp diff --git a/source/texture.h b/source/texture.h index 774b7e83..ad41e573 100644 --- a/source/texture.h +++ b/source/texture.h @@ -8,65 +8,20 @@ #include "gl.h" #include "pixelformat.h" #include "predicate.h" +#include "sampler.h" #include "resource.h" namespace Msp { namespace GL { -enum TextureFilter -{ - /// No filtering - NEAREST = GL_NEAREST, - - /// Bilinear filtering - LINEAR = GL_LINEAR, - - /// Mipmapping without filtering - NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, - - /// Linear filtering between two mipmap levels - NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, - - /// Bilinear filtering on the closest mipmap level - LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, - - /// Trilinear filtering between two mipmap levels - LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR -}; - - -enum TextureWrap -{ - /// Tile the texture infinitely - REPEAT = GL_REPEAT, - - /// Extend the texels at the edge of the texture to infinity - CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, - - /// Tile the texture, with every other repetition mirrored - MIRRORED_REPEAT = GL_MIRRORED_REPEAT -}; - - /** Base class for textures. This class only defines operations common for all -texture types and is not instantiable. For specifying images for textures, see -one of the dimensioned texture classes. - -A texture is generally rendered at a size that's either smaller or larger than -its native size, so that the texture coordinates do not exactly correspond to -the texels of the texture. The kind of filtering used, if any, is determined -by the minification and magnification filter parameters. The default is LINEAR -for magnification and NEAREST_MIPMAP_LINEAR for minification. - -When a mipmapped filter is in use, the texture consists of a stack of mipmap -images. Level 0 is the base image. Each level above 0 has half the size of -the previous level, rounded down and clamped to 1. The level with size 1 in -all dimensions is the last mipmap level. All levels must be allocated for the -texture to be usable. - -If texture coordinates fall outside of the principal range of the texture, -wrapping is applied. The default for all directions is REPEAT. +texture types and is not instantiable. For specifying images for textures, +see one of the dimensioned texture classes. + +A texture can consinst of a stack of images, called a mipmap. The dimensions +of each mipmap level are half that of the previous level. The mipmap stack +can be used for texture minification; see the Sampler class for details. */ class Texture: public Resource { @@ -93,6 +48,7 @@ protected: void max_anisotropy(float); void min_filter(TextureFilter); void mipmap_levels(unsigned); + void sampler(); void wrap(TextureWrap); void wrap_r(TextureWrap); void wrap_s(TextureWrap); @@ -101,14 +57,6 @@ protected: enum ParameterMask { - MIN_FILTER = 1, - MAG_FILTER = 2, - WRAP_S = 4, - WRAP_T = 8, - WRAP_R = 16, - COMPARE = 64, - COMPARE_FUNC = 128, - MAX_ANISOTROPY = 256, FORMAT_SWIZZLE = 512 }; @@ -123,16 +71,9 @@ protected: GLenum target; PixelFormat ifmt; FormatSwizzle swizzle; - TextureFilter min_filter; - TextureFilter mag_filter; - float max_anisotropy; - TextureWrap wrap_s; - TextureWrap wrap_t; - TextureWrap wrap_r; bool auto_gen_mipmap; - bool compare; - Predicate cmp_func; mutable int dirty_params; + Sampler default_sampler; static int swizzle_orders[]; @@ -147,27 +88,32 @@ protected: void set_internal_format(PixelFormat); PixelFormat get_upload_format(PixelFormat) const; +public: + Sampler &get_default_sampler() { return default_sampler; } + const Sampler &get_default_sampler() const { return default_sampler; } + +protected: void update_parameter(int) const; void set_parameter_i(GLenum, int) const; void set_parameter_f(GLenum, float) const; public: - void set_min_filter(TextureFilter); - void set_mag_filter(TextureFilter); + DEPRECATED void set_min_filter(TextureFilter); + DEPRECATED void set_mag_filter(TextureFilter); /** Sets filter for both minification and magnification. Since mipmapping is not applicable to magnification, LINEAR is used instead. */ - void set_filter(TextureFilter); + DEPRECATED void set_filter(TextureFilter); DEPRECATED void set_mipmap_levels(unsigned) { } - void set_max_anisotropy(float); + DEPRECATED void set_max_anisotropy(float); /** Sets the wrapping mode for all coordinates. */ - void set_wrap(TextureWrap); + DEPRECATED void set_wrap(TextureWrap); - void set_wrap_s(TextureWrap); - void set_wrap_t(TextureWrap); - void set_wrap_r(TextureWrap); + DEPRECATED void set_wrap_s(TextureWrap); + DEPRECATED void set_wrap_t(TextureWrap); + DEPRECATED void set_wrap_r(TextureWrap); static bool can_generate_mipmap(); @@ -184,10 +130,10 @@ public: comparison is enabled, the third component of the texture coordinate is compared against the texel value, and the result is returned as the texture sample. */ - void set_compare_enabled(bool); + DEPRECATED void set_compare_enabled(bool); /** Sets the function to use for depth comparison. */ - void set_compare_func(Predicate); + DEPRECATED void set_compare_func(Predicate); /// Loads a Graphics::Image from a file and uploads it to the texture. virtual void load_image(const std::string &, bool srgb = false); @@ -217,9 +163,6 @@ public: virtual UInt64 get_data_size() const { return 0; } }; - -bool is_mipmapped(TextureFilter); - } // namespace GL } // namespace Msp diff --git a/source/texture2d.cpp b/source/texture2d.cpp index 72c84428..78011d30 100644 --- a/source/texture2d.cpp +++ b/source/texture2d.cpp @@ -191,6 +191,7 @@ void Texture2D::unload() allocated = 0; // TODO check which params actually need refreshing dirty_params = -1; + default_sampler.unload(); } -- 2.45.2