From 8c406b7a4b5578eb50bf8b26de764ccf22a6a6f3 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 19 Mar 2013 22:42:12 -0300 Subject: [PATCH] Added anisotropic filtering functionality for images, consolidated mipmap methods into Image:setMipmapFilter(filtermode, sharpness, anisotropy), added love.graphics.setDefaultMipmapFilter(filtermode, sharpness, anisotropy) --- src/modules/graphics/opengl/Graphics.cpp | 12 +++ src/modules/graphics/opengl/Graphics.h | 6 ++ src/modules/graphics/opengl/Image.cpp | 78 +++++++++++++++---- src/modules/graphics/opengl/Image.h | 22 ++++-- src/modules/graphics/opengl/wrap_Graphics.cpp | 39 ++++++++++ src/modules/graphics/opengl/wrap_Graphics.h | 2 + src/modules/graphics/opengl/wrap_Image.cpp | 41 ++++------ src/modules/graphics/opengl/wrap_Image.h | 2 - 8 files changed, 158 insertions(+), 44 deletions(-) diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index a1f0ca2c4..b87148f67 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -639,6 +639,18 @@ const Image::Filter &Graphics::getDefaultImageFilter() const return Image::getDefaultFilter(); } +void Graphics::setDefaultMipmapFilter(Image::FilterMode filter, float sharpness, float anisotropy) +{ + Image::setDefaultMipmapFilter(filter); + Image::setDefaultMipmapSharpness(sharpness, anisotropy); +} + +void Graphics::getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness, float *anisotropy) const +{ + *filter = Image::getDefaultMipmapFilter(); + Image::getDefaultMipmapSharpness(sharpness, anisotropy); +} + void Graphics::setLineWidth(float width) { lineWidth = width; diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 98a44481a..700b004ea 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -319,6 +319,12 @@ public: **/ const Image::Filter &getDefaultImageFilter() const; + /** + * Default Image mipmap filtermode, sharpness, and anisotropy values. + **/ + void setDefaultMipmapFilter(Image::FilterMode filter, float sharpness, float anisotropy); + void getDefaultMipmapFilter(Image::FilterMode *filter, float *sharpness, float *anisotropy) const; + /** * Sets the line width. * @param width The new width of the line. diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index 29c4deaf3..9ef0b5264 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -33,11 +33,19 @@ namespace graphics namespace opengl { +float Image::maxMipmapSharpness = 0.0f; +float Image::maxMipmapAnisotropy = 0.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(0.0f) + , mipmapSharpness(defaultMipmapSharpness) + , mipmapAnisotropy(defaultMipmapAnisotropy) , mipmapsCreated(false) { data->retain(); @@ -64,6 +72,7 @@ Image::Image(love::image::ImageData *data) vertices[3].t = 0; filter = getDefaultFilter(); + filter.mipmap = defaultMipmapFilter; } Image::~Image() @@ -222,21 +231,34 @@ const Image::Wrap &Image::getWrap() const return wrap; } -void Image::setMipmapSharpness(float sharpness) +void Image::setMipmapSharpness(float sharpness, float anisotropy) { - if (!hasMipmapSharpnessSupport()) - return; + if (hasMipmapSharpnessSupport()) + { + // LOD bias has the range (-maxbias, maxbias) + mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f); - // LOD bias has the range (-maxbias, maxbias) - mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f); + bind(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper + } + else + mipmapSharpness = 0.0f; - bind(); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapSharpness); // negative bias is sharper + 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; } -float Image::getMipmapSharpness() const +void Image::getMipmapSharpness(float *sharpness, float *anisotropy) const { - return mipmapSharpness; + *sharpness = mipmapSharpness; + *anisotropy = mipmapAnisotropy; } void Image::bind() const @@ -259,9 +281,12 @@ void Image::unload() bool Image::loadVolatile() { - if (hasMipmapSharpnessSupport()) + 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 @@ -313,7 +338,7 @@ bool Image::loadVolatilePOT() mipmapsCreated = false; checkMipmapsCreated(); - setMipmapSharpness(mipmapSharpness); + setMipmapSharpness(mipmapSharpness, mipmapAnisotropy); return true; } @@ -343,7 +368,7 @@ bool Image::loadVolatileNPOT() mipmapsCreated = false; checkMipmapsCreated(); - setMipmapSharpness(mipmapSharpness); + setMipmapSharpness(mipmapSharpness, mipmapAnisotropy); return true; } @@ -377,6 +402,28 @@ void Image::drawv(const Matrix &t, const vertex *v) const glPopMatrix(); } +void Image::setDefaultMipmapSharpness(float sharpness, float anisotropy) +{ + defaultMipmapSharpness = sharpness; + defaultMipmapAnisotropy = anisotropy; +} + +void Image::getDefaultMipmapSharpness(float *sharpness, float *anisotropy) +{ + *sharpness = defaultMipmapSharpness; + *anisotropy = defaultMipmapAnisotropy; +} + +void Image::setDefaultMipmapFilter(Image::FilterMode f) +{ + defaultMipmapFilter = f; +} + +Image::FilterMode Image::getDefaultMipmapFilter() +{ + return defaultMipmapFilter; +} + bool Image::hasNpot() { return GLEE_VERSION_2_0 || GLEE_ARB_texture_non_power_of_two; @@ -392,6 +439,11 @@ 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 ea4f05bfb..f3fc97d97 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -104,9 +104,8 @@ public: const Image::Wrap &getWrap() const; - void setMipmapSharpness(float sharpness); - - float getMipmapSharpness() const; + void setMipmapSharpness(float sharpness, float anisotropy); + void getMipmapSharpness(float *sharpness, float *anisotropy) const; void bind() const; @@ -117,9 +116,15 @@ public: bool loadVolatile(); void unloadVolatile(); + static void setDefaultMipmapSharpness(float sharpness, float anisotropy); + static void getDefaultMipmapSharpness(float *sharpness, float *anisotropy); + static void setDefaultMipmapFilter(FilterMode f); + static FilterMode getDefaultMipmapFilter(); + static bool hasNpot(); static bool hasMipmapSupport(); static bool hasMipmapSharpnessSupport(); + static bool hasMipmapAnisotropySupport(); private: @@ -145,8 +150,8 @@ private: // Mipmap texture LOD bias (sharpness) value. float mipmapSharpness; - // Implementation-dependent min/max mipmap sharpness values. - float maxMipmapSharpness; + // Mipmap texture anisotropic filtering value. + float mipmapAnisotropy; // True if mipmaps have been created for this Image. bool mipmapsCreated; @@ -162,6 +167,13 @@ private: void checkMipmapsCreated(); + static float maxMipmapSharpness; + static float maxMipmapAnisotropy; + + static FilterMode defaultMipmapFilter; + static float defaultMipmapSharpness; + static float defaultMipmapAnisotropy; + }; // Image } // opengl diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index b1d60d6c8..5c44d7736 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -772,6 +772,43 @@ int w_getDefaultImageFilter(lua_State *L) return 2; } +int w_setDefaultMipmapFilter(lua_State *L) +{ + Image::FilterMode filter = Image::FILTER_NONE; + if (!lua_isnoneornil(L, 1)) + { + const char *str = luaL_checkstring(L, 1); + if (!Image::getConstant(str, filter)) + return luaL_error(L, "Invalid filter mode: %s", str); + } + + float sharpness = luaL_optnumber(L, 2, 0); + float anisotropy = luaL_optnumber(L, 3, 0); + + instance->setDefaultMipmapFilter(filter, sharpness, anisotropy); + + return 0; +} + +int w_getDefaultMipmapFilter(lua_State *L) +{ + Image::FilterMode filter; + float sharpness, anisotropy; + + instance->getDefaultMipmapFilter(&filter, &sharpness, &anisotropy); + + const char *str; + if (Image::getConstant(filter, str)) + lua_pushstring(L, str); + else + lua_pushnil(L); + + lua_pushnumber(L, sharpness); + lua_pushnumber(L, anisotropy); + + return 3; +} + int w_setLineWidth(lua_State *L) { float width = (float)luaL_checknumber(L, 1); @@ -1373,6 +1410,8 @@ static const luaL_Reg functions[] = { "setDefaultImageFilter", w_setDefaultImageFilter }, { "getBlendMode", w_getBlendMode }, { "getDefaultImageFilter", w_getDefaultImageFilter }, + { "setDefaultMipmapFilter", w_setDefaultMipmapFilter }, + { "getDefaultMipmapFilter", w_getDefaultMipmapFilter }, { "setLineWidth", w_setLineWidth }, { "setLineStyle", w_setLineStyle }, { "setLine", w_setLine }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index afd7c42f0..70a7cfa17 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -75,6 +75,8 @@ int w_setBlendMode(lua_State *L); int w_setDefaultImageFilter(lua_State *L); int w_getBlendMode(lua_State *L); int w_getDefaultImageFilter(lua_State *L); +int w_setDefaultMipmapFilter(lua_State *L); +int w_getDefaultMipmapFilter(lua_State *L); int w_setLineWidth(lua_State *L); int w_setLineStyle(lua_State *L); int w_setLine(lua_State *L); diff --git a/src/modules/graphics/opengl/wrap_Image.cpp b/src/modules/graphics/opengl/wrap_Image.cpp index fbf98857e..122437cec 100644 --- a/src/modules/graphics/opengl/wrap_Image.cpp +++ b/src/modules/graphics/opengl/wrap_Image.cpp @@ -115,6 +115,11 @@ int w_Image_setMipmapFilter(lua_State *L) { return luaL_error(L, "%s", e.what()); } + + float sharpness = luaL_optnumber(L, 3, 0); + float anisotropy = luaL_optnumber(L, 4, 0); + + t->setMipmapSharpness(sharpness, anisotropy); return 0; } @@ -122,15 +127,22 @@ int w_Image_setMipmapFilter(lua_State *L) int w_Image_getMipmapFilter(lua_State *L) { Image *t = luax_checkimage(L, 1); - const Image::Filter f = t->getFilter(); + + const Image::Filter &f = t->getFilter(); + + float sharpness, anisotropy; + t->getMipmapSharpness(&sharpness, &anisotropy); const char *mipmapstr; - if (!Image::getConstant(f.mipmap, mipmapstr)) - return 0; // only return a mipmap filter if mipmapping is enabled + if (Image::getConstant(f.mipmap, mipmapstr)) + lua_pushstring(L, mipmapstr); + else + lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled - lua_pushstring(L, mipmapstr); + lua_pushnumber(L, sharpness); + lua_pushnumber(L, anisotropy); - return 1; + return 3; } int w_Image_setWrap(lua_State *L) @@ -165,23 +177,6 @@ int w_Image_getWrap(lua_State *L) return 2; } -int w_Image_setMipmapSharpness(lua_State *L) -{ - Image *i = luax_checkimage(L, 1); - - float sharpness = (float) luaL_checknumber(L, 2); - i->setMipmapSharpness(sharpness); - - return 0; -} - -int w_Image_getMipmapSharpness(lua_State *L) -{ - Image *i = luax_checkimage(L, 1); - lua_pushnumber(L, i->getMipmapSharpness()); - return 1; -} - static const luaL_Reg functions[] = { { "getWidth", w_Image_getWidth }, @@ -193,8 +188,6 @@ static const luaL_Reg functions[] = { "getWrap", w_Image_getWrap }, { "setMipmapFilter", w_Image_setMipmapFilter }, { "getMipmapFilter", w_Image_getMipmapFilter }, - { "setMipmapSharpness", w_Image_setMipmapSharpness }, - { "getMipmapSharpness", w_Image_getMipmapSharpness }, { 0, 0 } }; diff --git a/src/modules/graphics/opengl/wrap_Image.h b/src/modules/graphics/opengl/wrap_Image.h index ac88456f2..8a60914de 100644 --- a/src/modules/graphics/opengl/wrap_Image.h +++ b/src/modules/graphics/opengl/wrap_Image.h @@ -42,8 +42,6 @@ int w_Image_setMipmapFilter(lua_State *L); int w_Image_getMipmapFilter(lua_State *L); int w_Image_setWrap(lua_State *L); int w_Image_getWrap(lua_State *L); -int w_Image_setMipmapSharpness(lua_State *L); -int w_Image_getMipmapSharpness(lua_State *L); extern "C" int luaopen_image(lua_State *L); } // opengl