diff --git a/src/modules/graphics/Image.cpp b/src/modules/graphics/Image.cpp index 52c37a180..08578339c 100644 --- a/src/modules/graphics/Image.cpp +++ b/src/modules/graphics/Image.cpp @@ -26,6 +26,7 @@ namespace graphics { Image::Filter Image::defaultFilter; +float Image::defaultAnisotropy = 1.0f; Image::Filter::Filter() : min(FILTER_LINEAR) @@ -54,6 +55,16 @@ const Image::Filter &Image::getDefaultFilter() return defaultFilter; } +void Image::setDefaultAnisotropy(float anisotropy) +{ + defaultAnisotropy = anisotropy; +} + +float Image::getDefaultAnisotropy() +{ + return defaultAnisotropy; +} + bool Image::getConstant(const char *in, FilterMode &out) { return filterModes.find(in, out); diff --git a/src/modules/graphics/Image.h b/src/modules/graphics/Image.h index 2203293d7..f788d51fa 100644 --- a/src/modules/graphics/Image.h +++ b/src/modules/graphics/Image.h @@ -71,6 +71,10 @@ public: static void setDefaultFilter(const Filter &f); static const Filter &getDefaultFilter(); + // The default amount of anisotropic filtering. + static void setDefaultAnisotropy(float anisotropy); + static float getDefaultAnisotropy(); + static bool getConstant(const char *in, FilterMode &out); static bool getConstant(FilterMode in, const char *&out); static bool getConstant(const char *in, WrapMode &out); @@ -78,9 +82,12 @@ public: private: - // The default image filter + // The default image filter. static Filter defaultFilter; + // The default amount of anisotropic filtering. + static float defaultAnisotropy; + static StringMap::Entry filterModeEntries[]; static StringMap filterModes; static StringMap::Entry wrapModeEntries[]; diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 27de68d70..4f977213f 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -19,8 +19,10 @@ **/ #include "Canvas.h" +#include "Image.h" #include "Graphics.h" #include "common/Matrix.h" +#include "common/config.h" #include // For memcpy @@ -315,6 +317,7 @@ Canvas::Canvas(int width, int height, TextureType texture_type) vertices[3].t = 0; settings.filter = Image::getDefaultFilter(); + settings.anisotropy = Image::getDefaultAnisotropy(); getStrategy(); @@ -494,6 +497,24 @@ Image::Wrap Canvas::getWrap() const return getTextureWrap(); } +void Canvas::setAnisotropy(float anisotropy) +{ + if (Image::hasAnisotropicFilteringSupport()) + { + settings.anisotropy = std::min(std::max(anisotropy, 1.0f), Image::getMaxAnisotropy()); + + bindTexture(img); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, settings.anisotropy); + } + else + settings.anisotropy = 1.0f; +} + +float Canvas::getAnisotropy() const +{ + return settings.anisotropy; +} + bool Canvas::loadVolatile() { status = strategy->createFBO(fbo, depth_stencil, img, width, height, texture_type); @@ -502,6 +523,7 @@ bool Canvas::loadVolatile() setFilter(settings.filter); setWrap(settings.wrap); + setAnisotropy(settings.anisotropy); Color c; c.r = c.g = c.b = c.a = 0; clear(c); diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index 81162e68e..1e6ab8502 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -72,6 +72,9 @@ public: void setWrap(const Image::Wrap &w); Image::Wrap getWrap() const; + void setAnisotropy(float anisotropy); + float getAnisotropy() const; + int getWidth(); int getHeight(); @@ -119,6 +122,7 @@ private: { Image::Filter filter; Image::Wrap wrap; + float anisotropy; } settings; void drawv(const Matrix &t, const vertex *v) const; diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index 9cd5db7fe..f51179d6f 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -47,6 +47,7 @@ Font::Font(love::font::Rasterizer *r, const Image::Filter &filter) , height(r->getHeight()) , lineHeight(1) , mSpacing(1) + , anisotropy(Image::getDefaultAnisotropy()) , filter(filter) { // try to find the best texture size match for the font size @@ -166,6 +167,7 @@ void Font::createTexture() &emptyData[0]); setFilter(filter); + setAnisotropy(anisotropy); } Font::Glyph *Font::addGlyph(unsigned int glyph) @@ -513,6 +515,28 @@ const Image::Filter &Font::getFilter() return filter; } +void Font::setAnisotropy(float anisotropy) +{ + if (Image::hasAnisotropicFilteringSupport()) + { + this->anisotropy = std::min(std::max(anisotropy, 1.0f), Image::getMaxAnisotropy()); + + std::vector::const_iterator it; + for (it = textures.begin(); it != textures.end(); ++it) + { + bindTexture(*it); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->anisotropy); + } + } + else + this->anisotropy = 1.0f; +} + +float Font::getAnisotropy() const +{ + return anisotropy; +} + bool Font::loadVolatile() { createTexture(); diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index 9a157e551..d0ea5d472 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -129,6 +129,9 @@ public: void setFilter(const Image::Filter &f); const Image::Filter &getFilter(); + void setAnisotropy(float anisotropy); + float getAnisotropy() const; + // Implements Volatile. bool loadVolatile(); void unloadVolatile(); @@ -183,6 +186,8 @@ private: float lineHeight; float mSpacing; // modifies the spacing by multiplying it with this value + float anisotropy; + int texture_size_index; int texture_width; int texture_height; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index b87148f67..0447379c5 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -639,16 +639,26 @@ const Image::Filter &Graphics::getDefaultImageFilter() const return Image::getDefaultFilter(); } -void Graphics::setDefaultMipmapFilter(Image::FilterMode filter, float sharpness, float anisotropy) +void Graphics::setDefaultAnisotropy(float anisotropy) { - Image::setDefaultMipmapFilter(filter); - Image::setDefaultMipmapSharpness(sharpness, anisotropy); + Image::setDefaultAnisotropy(anisotropy); } -void Graphics::getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness, float *anisotropy) const +float Graphics::getDefaultAnisotropy() const +{ + return Image::getDefaultAnisotropy(); +} + +void Graphics::setDefaultMipmapFilter(Image::FilterMode filter, float sharpness) +{ + Image::setDefaultMipmapFilter(filter); + Image::setDefaultMipmapSharpness(sharpness); +} + +void Graphics::getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness) const { *filter = Image::getDefaultMipmapFilter(); - Image::getDefaultMipmapSharpness(sharpness, anisotropy); + *sharpness = Image::getDefaultMipmapSharpness(); } void Graphics::setLineWidth(float width) diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 700b004ea..eb8cfbc83 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -320,10 +320,16 @@ public: const Image::Filter &getDefaultImageFilter() const; /** - * Default Image mipmap filtermode, sharpness, and anisotropy values. + * Default texture anisotropic filtering level. **/ - void setDefaultMipmapFilter(Image::FilterMode filter, float sharpness, float anisotropy); - void getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness, float *anisotropy) const; + void setDefaultAnisotropy(float anisotropy); + float getDefaultAnisotropy() const; + + /** + * Default Image mipmap filtermode and sharpness values. + **/ + void setDefaultMipmapFilter(Image::FilterMode filter, float sharpness); + void getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness) const; /** * Sets the line width. diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 9ef0b5264..b8b57d2ab 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -34,19 +34,18 @@ namespace opengl { float Image::maxMipmapSharpness = 0.0f; -float Image::maxMipmapAnisotropy = 0.0f; +float Image::maxAnisotropy = 1.0f; Image::FilterMode Image::defaultMipmapFilter = Image::FILTER_NONE; float Image::defaultMipmapSharpness = 0.0f; -float Image::defaultMipmapAnisotropy = 0.0f; Image::Image(love::image::ImageData *data) : width((float)(data->getWidth())) , height((float)(data->getHeight())) , texture(0) , mipmapSharpness(defaultMipmapSharpness) - , mipmapAnisotropy(defaultMipmapAnisotropy) , mipmapsCreated(false) + , anisotropy(getDefaultAnisotropy()) { data->retain(); this->data = data; @@ -231,7 +230,7 @@ const Image::Wrap &Image::getWrap() const return wrap; } -void Image::setMipmapSharpness(float sharpness, float anisotropy) +void Image::setMipmapSharpness(float sharpness) { if (hasMipmapSharpnessSupport()) { @@ -243,22 +242,29 @@ void Image::setMipmapSharpness(float sharpness, float anisotropy) } else mipmapSharpness = 0.0f; - - if (hasMipmapAnisotropySupport()) - { - mipmapAnisotropy = std::min(std::max(anisotropy, 0.0f), maxMipmapAnisotropy); - - bind(); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, mipmapAnisotropy); - } - else - mipmapAnisotropy = 0.0f; } -void Image::getMipmapSharpness(float *sharpness, float *anisotropy) const +float Image::getMipmapSharpness() const { - *sharpness = mipmapSharpness; - *anisotropy = mipmapAnisotropy; + return mipmapSharpness; +} + +void Image::setAnisotropy(float anisotropy) +{ + if (hasAnisotropicFilteringSupport()) + { + this->anisotropy = std::min(std::max(anisotropy, 1.0f), getMaxAnisotropy()); + + bind(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->anisotropy); + } + else + this->anisotropy = 1.0f; +} + +float Image::getAnisotropy() const +{ + return anisotropy; } void Image::bind() const @@ -284,9 +290,6 @@ bool Image::loadVolatile() if (hasMipmapSharpnessSupport() && maxMipmapSharpness == 0.0f) glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxMipmapSharpness); - if (hasMipmapAnisotropySupport() && maxMipmapAnisotropy == 0.0f) - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxMipmapAnisotropy); - if (hasNpot()) return loadVolatileNPOT(); else @@ -338,7 +341,9 @@ bool Image::loadVolatilePOT() mipmapsCreated = false; checkMipmapsCreated(); - setMipmapSharpness(mipmapSharpness, mipmapAnisotropy); + + setMipmapSharpness(mipmapSharpness); + setAnisotropy(anisotropy); return true; } @@ -368,7 +373,9 @@ bool Image::loadVolatileNPOT() mipmapsCreated = false; checkMipmapsCreated(); - setMipmapSharpness(mipmapSharpness, mipmapAnisotropy); + + setMipmapSharpness(mipmapSharpness); + setAnisotropy(anisotropy); return true; } @@ -402,16 +409,14 @@ void Image::drawv(const Matrix &t, const vertex *v) const glPopMatrix(); } -void Image::setDefaultMipmapSharpness(float sharpness, float anisotropy) +void Image::setDefaultMipmapSharpness(float sharpness) { defaultMipmapSharpness = sharpness; - defaultMipmapAnisotropy = anisotropy; } -void Image::getDefaultMipmapSharpness(float *sharpness, float *anisotropy) +float Image::getDefaultMipmapSharpness() { - *sharpness = defaultMipmapSharpness; - *anisotropy = defaultMipmapAnisotropy; + return defaultMipmapSharpness; } void Image::setDefaultMipmapFilter(Image::FilterMode f) @@ -424,11 +429,24 @@ Image::FilterMode Image::getDefaultMipmapFilter() return defaultMipmapFilter; } +float Image::getMaxAnisotropy() +{ + if (hasAnisotropicFilteringSupport() && maxAnisotropy == 1.0f) + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy); + + return maxAnisotropy; +} + bool Image::hasNpot() { return GLEE_VERSION_2_0 || GLEE_ARB_texture_non_power_of_two; } +bool Image::hasAnisotropicFilteringSupport() +{ + return GLEE_EXT_texture_filter_anisotropic; +} + bool Image::hasMipmapSupport() { return GLEE_VERSION_1_4 || GLEE_SGIS_generate_mipmap; @@ -439,11 +457,6 @@ bool Image::hasMipmapSharpnessSupport() return GLEE_VERSION_1_4 || GLEE_EXT_texture_lod_bias; } -bool Image::hasMipmapAnisotropySupport() -{ - return GLEE_EXT_texture_filter_anisotropic; -} - } // opengl } // graphics } // love diff --git a/src/modules/graphics/opengl/Image.h b/src/modules/graphics/opengl/Image.h index f3fc97d97..6bd8f6fb9 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -104,8 +104,11 @@ public: const Image::Wrap &getWrap() const; - void setMipmapSharpness(float sharpness, float anisotropy); - void getMipmapSharpness(float *sharpness, float *anisotropy) const; + void setAnisotropy(float anisotropy); + float getAnisotropy() const; + + void setMipmapSharpness(float sharpness); + float getMipmapSharpness() const; void bind() const; @@ -116,15 +119,17 @@ public: bool loadVolatile(); void unloadVolatile(); - static void setDefaultMipmapSharpness(float sharpness, float anisotropy); - static void getDefaultMipmapSharpness(float *sharpness, float *anisotropy); + static void setDefaultMipmapSharpness(float sharpness); + static float getDefaultMipmapSharpness(); static void setDefaultMipmapFilter(FilterMode f); static FilterMode getDefaultMipmapFilter(); + static float getMaxAnisotropy(); + static bool hasNpot(); + static bool hasAnisotropicFilteringSupport(); static bool hasMipmapSupport(); static bool hasMipmapSharpnessSupport(); - static bool hasMipmapAnisotropySupport(); private: @@ -150,12 +155,12 @@ private: // Mipmap texture LOD bias (sharpness) value. float mipmapSharpness; - // Mipmap texture anisotropic filtering value. - float mipmapAnisotropy; - // True if mipmaps have been created for this Image. bool mipmapsCreated; + // Anisotropic filtering value. + float anisotropy; + // The image's filter mode Image::Filter filter; @@ -168,11 +173,10 @@ private: void checkMipmapsCreated(); static float maxMipmapSharpness; - static float maxMipmapAnisotropy; + static float maxAnisotropy; static FilterMode defaultMipmapFilter; static float defaultMipmapSharpness; - static float defaultMipmapAnisotropy; }; // Image diff --git a/src/modules/graphics/opengl/wrap_Canvas.cpp b/src/modules/graphics/opengl/wrap_Canvas.cpp index 39728391b..7a8dc0a6f 100644 --- a/src/modules/graphics/opengl/wrap_Canvas.cpp +++ b/src/modules/graphics/opengl/wrap_Canvas.cpp @@ -101,6 +101,9 @@ int w_Canvas_setFilter(lua_State *L) canvas->setFilter(f); + float anisotropy = (float) luaL_optnumber(L, 4, 1.0); + canvas->setAnisotropy(anisotropy); + return 0; } @@ -118,7 +121,9 @@ int w_Canvas_getFilter(lua_State *L) lua_pushstring(L, minstr); lua_pushstring(L, magstr); - return 2; + lua_pushnumber(L, canvas->getAnisotropy()); + + return 3; } int w_Canvas_setWrap(lua_State *L) diff --git a/src/modules/graphics/opengl/wrap_Font.cpp b/src/modules/graphics/opengl/wrap_Font.cpp index fda13c776..4a88ca6df 100644 --- a/src/modules/graphics/opengl/wrap_Font.cpp +++ b/src/modules/graphics/opengl/wrap_Font.cpp @@ -112,6 +112,9 @@ int w_Font_setFilter(lua_State *L) return luaL_error(L, "%s", e.what()); } + float anisotropy = (float) luaL_optnumber(L, 4, 1.0); + t->setAnisotropy(anisotropy); + return 0; } @@ -125,7 +128,8 @@ int w_Font_getFilter(lua_State *L) Image::getConstant(f.mag, magstr); lua_pushstring(L, minstr); lua_pushstring(L, magstr); - return 2; + lua_pushnumber(L, t->getAnisotropy()); + return 3; } int w_Font_getAscent(lua_State *L) diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 5c44d7736..e3d47e5d5 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -738,6 +738,9 @@ int w_setDefaultImageFilter(lua_State *L) instance->setDefaultImageFilter(f); + float anisotropy = (float) luaL_optnumber(L, 3, 1.0); + instance->setDefaultAnisotropy(anisotropy); + return 0; } @@ -764,12 +767,13 @@ int w_getDefaultImageFilter(lua_State *L) const char *minstr; const char *magstr; if (!Image::getConstant(f.min, minstr)) - return luaL_error(L, "Unknown filter mode for argument #1"); + return luaL_error(L, "Unknown minification filter mode"); if (!Image::getConstant(f.mag, magstr)) - return luaL_error(L, "Unknown filter mode for argument #2"); + return luaL_error(L, "Unknown magnification filter mode"); lua_pushstring(L, minstr); lua_pushstring(L, magstr); - return 2; + lua_pushnumber(L, instance->getDefaultAnisotropy()); + return 3; } int w_setDefaultMipmapFilter(lua_State *L) @@ -783,9 +787,8 @@ int w_setDefaultMipmapFilter(lua_State *L) } float sharpness = luaL_optnumber(L, 2, 0); - float anisotropy = luaL_optnumber(L, 3, 0); - instance->setDefaultMipmapFilter(filter, sharpness, anisotropy); + instance->setDefaultMipmapFilter(filter, sharpness); return 0; } @@ -793,9 +796,9 @@ int w_setDefaultMipmapFilter(lua_State *L) int w_getDefaultMipmapFilter(lua_State *L) { Image::FilterMode filter; - float sharpness, anisotropy; + float sharpness; - instance->getDefaultMipmapFilter(&filter, &sharpness, &anisotropy); + instance->getDefaultMipmapFilter(&filter, &sharpness); const char *str; if (Image::getConstant(filter, str)) @@ -804,9 +807,8 @@ int w_getDefaultMipmapFilter(lua_State *L) lua_pushnil(L); lua_pushnumber(L, sharpness); - lua_pushnumber(L, anisotropy); - return 3; + return 2; } int w_setLineWidth(lua_State *L) diff --git a/src/modules/graphics/opengl/wrap_Image.cpp b/src/modules/graphics/opengl/wrap_Image.cpp index 122437cec..c66b63965 100644 --- a/src/modules/graphics/opengl/wrap_Image.cpp +++ b/src/modules/graphics/opengl/wrap_Image.cpp @@ -77,6 +77,9 @@ int w_Image_setFilter(lua_State *L) return luaL_error(L, "%s", e.what()); } + float anisotropy = (float) luaL_optnumber(L, 4, 1.0); + t->setAnisotropy(anisotropy); + return 0; } @@ -90,7 +93,8 @@ int w_Image_getFilter(lua_State *L) Image::getConstant(f.mag, magstr); lua_pushstring(L, minstr); lua_pushstring(L, magstr); - return 2; + lua_pushnumber(L, t->getAnisotropy()); + return 3; } int w_Image_setMipmapFilter(lua_State *L) @@ -117,9 +121,8 @@ int w_Image_setMipmapFilter(lua_State *L) } float sharpness = luaL_optnumber(L, 3, 0); - float anisotropy = luaL_optnumber(L, 4, 0); - t->setMipmapSharpness(sharpness, anisotropy); + t->setMipmapSharpness(sharpness); return 0; } @@ -130,19 +133,15 @@ int w_Image_getMipmapFilter(lua_State *L) const Image::Filter &f = t->getFilter(); - float sharpness, anisotropy; - t->getMipmapSharpness(&sharpness, &anisotropy); - const char *mipmapstr; if (Image::getConstant(f.mipmap, mipmapstr)) lua_pushstring(L, mipmapstr); else lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled - lua_pushnumber(L, sharpness); - lua_pushnumber(L, anisotropy); + lua_pushnumber(L, t->getMipmapSharpness()); - return 3; + return 2; } int w_Image_setWrap(lua_State *L)