Browse Source

Added anisotropic filtering functionality for images, consolidated mipmap methods into Image:setMipmapFilter(filtermode, sharpness, anisotropy), added love.graphics.setDefaultMipmapFilter(filtermode, sharpness, anisotropy)

Alex Szpakowski 12 years ago
parent
commit
8c406b7a4b

+ 12 - 0
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;

+ 6 - 0
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.

+ 65 - 13
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

+ 17 - 5
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

+ 39 - 0
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 },

+ 2 - 0
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);

+ 17 - 24
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 }
 };
 

+ 0 - 2
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