Implemented trilinear filtering, mipmap level setting and anisotropic filtering

master
Tomasz Kapuściński 2015-05-06 17:55:10 +02:00
parent 05bf5be6f4
commit d3b052f19b
7 changed files with 178 additions and 36 deletions

View File

@ -91,7 +91,8 @@ enum TransformType
{
TRANSFORM_WORLD,
TRANSFORM_VIEW,
TRANSFORM_PROJECTION
TRANSFORM_PROJECTION,
TRANSFORM_TEXTURE
};
/**

View File

@ -52,6 +52,19 @@ enum TexImgFormat
TEX_IMG_BGRA
};
/**
* \enum TexFilter
* \brief General texture filtering mode
*
* Corresponds to typical options in game graphics settings.
*/
enum TexFilter
{
TEX_FILTER_NEAREST,
TEX_FILTER_BILINEAR,
TEX_FILTER_TRILINEAR
};
/**
* \enum TexMinFilter
* \brief Texture minification filter
@ -135,10 +148,8 @@ struct TextureCreateParams
bool mipmap;
//! Format of source image data
TexImgFormat format;
//! Minification filter
TexMinFilter minFilter;
//! Magnification filter
TexMagFilter magFilter;
//! General texture filtering mode
TexFilter filter;
//! Pad the image to nearest power of 2 dimensions
bool padToNearestPowerOfTwo;
@ -153,8 +164,7 @@ struct TextureCreateParams
mipmap = false;
padToNearestPowerOfTwo = false;
minFilter = TEX_MIN_FILTER_NEAREST;
magFilter = TEX_MAG_FILTER_NEAREST;
filter = TEX_FILTER_NEAREST;
}
};

View File

@ -114,6 +114,8 @@ CEngine::CEngine(CApplication *app)
m_terrainVision = 1000.0f;
m_gadgetQuantity = 1.0f;
m_textureQuality = 1;
m_textureMipmapLevel = 1;
m_textureAnisotropy = 1;
m_totoMode = true;
m_lensMode = true;
m_waterMode = true;
@ -158,15 +160,34 @@ CEngine::CEngine(CApplication *app)
m_lastFrameTime = GetSystemUtils()->CreateTimeStamp();
m_currentFrameTime = GetSystemUtils()->CreateTimeStamp();
TexFilter filter = TEX_FILTER_BILINEAR;
bool mipmaps = false;
int value;
if (CProfile::GetInstance().GetIntProperty("Setup", "FilterMode", value))
{
if (value == 1) filter = TEX_FILTER_NEAREST;
else if (value == 2) filter = TEX_FILTER_BILINEAR;
else if (value == 3) filter = TEX_FILTER_TRILINEAR, mipmaps = true;
}
if (CProfile::GetInstance().GetIntProperty("Setup", "MipmapLevel", value))
{
m_textureMipmapLevel = value;
}
if (CProfile::GetInstance().GetIntProperty("Setup", "Anisotropy", value))
{
m_textureAnisotropy = value;
}
m_defaultTexParams.format = TEX_IMG_AUTO;
m_defaultTexParams.mipmap = true;
m_defaultTexParams.minFilter = TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
m_defaultTexParams.magFilter = TEX_MAG_FILTER_LINEAR;
m_defaultTexParams.mipmap = mipmaps;
m_defaultTexParams.filter = filter;
m_terrainTexParams.format = TEX_IMG_AUTO;
m_terrainTexParams.mipmap = false;
m_terrainTexParams.minFilter = TEX_MIN_FILTER_LINEAR;
m_terrainTexParams.magFilter = TEX_MAG_FILTER_LINEAR;
m_terrainTexParams.mipmap = mipmaps;
m_terrainTexParams.filter = filter;
}
CEngine::~CEngine()
@ -282,8 +303,7 @@ bool CEngine::Create()
TextureCreateParams params;
params.format = TEX_IMG_AUTO;
params.minFilter = TEX_MIN_FILTER_NEAREST;
params.magFilter = TEX_MAG_FILTER_NEAREST;
params.filter = TEX_FILTER_NEAREST;
params.mipmap = false;
m_miceTexture = LoadTexture("textures/interface/mouse.png", params);
@ -2908,6 +2928,43 @@ int CEngine::GetTextureQuality()
return m_textureQuality;
}
void CEngine::SetTextureFilterMode(TexFilter value)
{
m_defaultTexParams.filter = value;
m_terrainTexParams.filter = value;
}
TexFilter CEngine::GetTextureFilterMode()
{
return m_terrainTexParams.filter;
}
void CEngine::SetTextureMipmapLevel(int value)
{
if (value < 1) value = 1;
if (value > 16) value = 16;
m_textureMipmapLevel = value;
}
int CEngine::GetTextureMipmapLevel()
{
return m_textureMipmapLevel;
}
void CEngine::SetTextureAnisotropyLevel(int value)
{
if (value < 1) value = 1;
if (value > 16) value = 16;
m_textureAnisotropy = value;
}
int CEngine::GetTextureAnisotropyLevel()
{
return m_textureAnisotropy;
}
void CEngine::SetTotoMode(bool present)
{
m_totoMode = present;

View File

@ -1116,6 +1116,24 @@ public:
int GetTextureQuality();
//@}
//@{
//! Management the texture filter mode
void SetTextureFilterMode(TexFilter value);
TexFilter GetTextureFilterMode();
//@}
//@{
//! Management the mipmap level for textures
void SetTextureMipmapLevel(int value);
int GetTextureMipmapLevel();
//@}
//@{
//! Management the anisotropy level for textures
void SetTextureAnisotropyLevel(int value);
int GetTextureAnisotropyLevel();
//@}
//@{
//! Management mode of toto
void SetTotoMode(bool present);
@ -1414,6 +1432,10 @@ protected:
TextureCreateParams m_defaultTexParams;
//! Create params for terrain textures
TextureCreateParams m_terrainTexParams;
//! Requested texture mipmap level
int m_textureMipmapLevel;
//! Requested texture anisotropy level
int m_textureAnisotropy;
//! Map of loaded textures (by name)
std::map<std::string, Texture> m_texNameMap;

View File

@ -1014,8 +1014,7 @@ CharTexture CText::CreateCharTexture(UTF8Char ch, CachedFont* font)
TextureCreateParams createParams;
createParams.format = TEX_IMG_RGBA;
createParams.minFilter = TEX_MIN_FILTER_NEAREST;
createParams.magFilter = TEX_MAG_FILTER_NEAREST;
createParams.filter = TEX_FILTER_NEAREST;
createParams.mipmap = false;
Texture tex = m_device->CreateTexture(&data, createParams);

View File

@ -19,6 +19,7 @@
#include "graphics/opengl/gldevice.h"
#include "graphics/engine/engine.h"
#include "common/config.h"
#include "common/image.h"
@ -69,6 +70,8 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config)
m_multitextureAvailable = false;
m_vboAvailable = false;
m_vertexBufferType = VBT_DISPLAY_LIST;
m_anisotropyAvailable = false;
m_maxAnisotropy = 1;
}
@ -205,6 +208,23 @@ bool CGLDevice::Create()
if (!m_multitextureAvailable)
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
// Detect support of anisotropic filtering
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
if(m_anisotropyAvailable)
{
// Obtain maximum anisotropy level available
float level;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &level);
m_maxAnisotropy = static_cast<int>(level);
GetLogger()->Info("Anisotropic filtering available\n");
GetLogger()->Info("Maximum anisotropy: %d\n", m_maxAnisotropy);
}
else
{
GetLogger()->Info("Anisotropic filtering not available\n");
}
if (m_config.vboMode == VBO_MODE_ENABLE)
{
GetLogger()->Info("VBO enabled by override - using VBOs\n");
@ -360,6 +380,12 @@ void CGLDevice::SetTransform(TransformType type, const Math::Matrix &matrix)
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(m_projectionMat.Array());
}
else if (type == TRANSFORM_TEXTURE)
{
m_textureMat = matrix;
glMatrixMode(GL_TEXTURE);
glLoadMatrixf(m_textureMat.Array());
}
else
{
assert(false);
@ -511,7 +537,7 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
if (!Math::IsPowerOfTwo(result.size.x) || !Math::IsPowerOfTwo(result.size.y))
GetLogger()->Warn("Creating non-power-of-2 texture (%dx%d)!\n", result.size.x, result.size.y);
result.originalSize = result.size;
// Use & enable 1st texture stage
@ -523,31 +549,52 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
glGenTextures(1, &result.id);
glBindTexture(GL_TEXTURE_2D, result.id);
// Set params
// Set texture parameters
GLint minF = 0, magF = 0;
int mipmapLevel = 1;
GLint minF = 0;
if (params.minFilter == TEX_MIN_FILTER_NEAREST) minF = GL_NEAREST;
else if (params.minFilter == TEX_MIN_FILTER_LINEAR) minF = GL_LINEAR;
else if (params.minFilter == TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST) minF = GL_NEAREST_MIPMAP_NEAREST;
else if (params.minFilter == TEX_MIN_FILTER_LINEAR_MIPMAP_NEAREST) minF = GL_LINEAR_MIPMAP_NEAREST;
else if (params.minFilter == TEX_MIN_FILTER_NEAREST_MIPMAP_LINEAR) minF = GL_NEAREST_MIPMAP_LINEAR;
else if (params.minFilter == TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR) minF = GL_LINEAR_MIPMAP_LINEAR;
else assert(false);
switch (params.filter)
{
case TEX_FILTER_NEAREST:
minF = GL_NEAREST;
magF = GL_NEAREST;
break;
case TEX_FILTER_BILINEAR:
minF = GL_LINEAR;
magF = GL_LINEAR;
break;
case TEX_FILTER_TRILINEAR:
minF = GL_LINEAR_MIPMAP_LINEAR;
magF = GL_LINEAR;
mipmapLevel = CEngine::GetInstance().GetTextureMipmapLevel();
break;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minF);
GLint magF = 0;
if (params.magFilter == TEX_MAG_FILTER_NEAREST) magF = GL_NEAREST;
else if (params.magFilter == TEX_MAG_FILTER_LINEAR) magF = GL_LINEAR;
else assert(false);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magF);
// Set mipmap level and automatic mipmap generation if neccesary
if (params.mipmap)
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipmapLevel - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
}
else
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
{
// Has to be set to 0 because no mipmaps are generated
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
}
// Set anisotropy level if available
if (m_anisotropyAvailable)
{
float level = Math::Min(m_maxAnisotropy, CEngine::GetInstance().GetTextureAnisotropyLevel());
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level);
}
bool convert = false;
GLenum sourceFormat = 0;
@ -653,7 +700,7 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
actualSurface = convertedSurface;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, actualSurface->w, actualSurface->h,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, actualSurface->w, actualSurface->h,
0, sourceFormat, GL_UNSIGNED_BYTE, actualSurface->pixels);
SDL_FreeSurface(convertedSurface);

View File

@ -205,6 +205,8 @@ private:
Math::Matrix m_modelviewMat;
//! Current projection matrix
Math::Matrix m_projectionMat;
//! Current texture matrix
Math::Matrix m_textureMat;
//! The current material
Material m_material;
@ -247,6 +249,10 @@ private:
bool m_multitextureAvailable;
//! Whether to use VBOs or display lists
bool m_vboAvailable;
//! Whether anisotropic filtering is available
bool m_anisotropyAvailable;
//! Maximum anisotropy level
int m_maxAnisotropy;
//! Which vertex buffer type to use
VertexBufferType m_vertexBufferType;
//! Map of saved VBO objects