Split up texture filtering properties of SMaterialLayer into MinFilter and MagFilter

You can now set the filter used when scaling textures down and the filter used when scaling textures up separately.
This commit is contained in:
Gregor Parzefall 2023-06-23 13:58:50 +02:00 committed by sfan5
parent 9e0189019e
commit 5ececc7d29
10 changed files with 128 additions and 101 deletions

@ -37,11 +37,11 @@ namespace video
//! Corresponds to SMaterial::FrontfaceCulling.
EMF_FRONT_FACE_CULLING = 0x80,
//! Corresponds to SMaterialLayer::BilinearFilter.
EMF_BILINEAR_FILTER = 0x100,
//! Corresponds to SMaterialLayer::MinFilter.
EMF_MIN_FILTER = 0x100,
//! Corresponds to SMaterialLayer::TrilinearFilter.
EMF_TRILINEAR_FILTER = 0x200,
//! Corresponds to SMaterialLayer::MagFilter.
EMF_MAG_FILTER = 0x200,
//! Corresponds to SMaterialLayer::AnisotropicFilter.
EMF_ANISOTROPIC_FILTER = 0x400,

@ -426,7 +426,6 @@ namespace video
f32 PolygonOffsetSlopeScale;
//! Draw as wireframe or filled triangles? Default: false
/** The user can access a material flag using \code material.Wireframe = true; \endcode */
bool Wireframe:1;
//! Draw as point cloud or filled triangles? Default: false

@ -43,6 +43,30 @@ namespace video
"texture_clamp_mirror_clamp_to_edge",
"texture_clamp_mirror_clamp_to_border", 0};
//! Texture minification filter.
/** Used when scaling textures down. */
enum E_TEXTURE_MIN_FILTER {
//! Nearest-neighbor interpolation.
ETMINF_NEAREST = 0,
//! Linear interpolation.
ETMINF_BILINEAR,
//! Linear interpolation across mipmaps.
/** Is equivalent to ETMINF_BILINEAR if mipmaps are disabled.
Only available as a minification filter since mipmaps are only used
when scaling down. */
ETMINF_TRILINEAR,
};
//! Texture magnification filter.
/** Used when scaling textures up. */
enum E_TEXTURE_MAG_FILTER {
//! Nearest-neighbor interpolation.
ETMAGF_NEAREST = 0,
//! Linear interpolation.
ETMAGF_BILINEAR,
};
//! Struct for holding material parameters which exist per texture layer
// Note for implementors: Serialization is in CNullDriver
class SMaterialLayer
@ -50,7 +74,7 @@ namespace video
public:
//! Default constructor
SMaterialLayer() : Texture(0), TextureWrapU(ETC_REPEAT), TextureWrapV(ETC_REPEAT), TextureWrapW(ETC_REPEAT),
BilinearFilter(true), TrilinearFilter(false), AnisotropicFilter(0), LODBias(0), TextureMatrix(0)
MinFilter(ETMINF_BILINEAR), MagFilter(ETMAGF_BILINEAR), AnisotropicFilter(0), LODBias(0), TextureMatrix(0)
{
}
@ -104,8 +128,8 @@ namespace video
TextureWrapU = other.TextureWrapU;
TextureWrapV = other.TextureWrapV;
TextureWrapW = other.TextureWrapW;
BilinearFilter = other.BilinearFilter;
TrilinearFilter = other.TrilinearFilter;
MinFilter = other.MinFilter;
MagFilter = other.MagFilter;
AnisotropicFilter = other.AnisotropicFilter;
LODBias = other.LODBias;
@ -157,8 +181,8 @@ namespace video
TextureWrapU != b.TextureWrapU ||
TextureWrapV != b.TextureWrapV ||
TextureWrapW != b.TextureWrapW ||
BilinearFilter != b.BilinearFilter ||
TrilinearFilter != b.TrilinearFilter ||
MinFilter != b.MinFilter ||
MagFilter != b.MagFilter ||
AnisotropicFilter != b.AnisotropicFilter ||
LODBias != b.LODBias;
if (different)
@ -184,13 +208,11 @@ namespace video
u8 TextureWrapV:4;
u8 TextureWrapW:4;
//! Is bilinear filtering enabled? Default: true
bool BilinearFilter:1;
//! Minification (downscaling) filter
E_TEXTURE_MIN_FILTER MinFilter;
//! Is trilinear filtering enabled? Default: false
/** If the trilinear filter flag is enabled,
the bilinear filtering flag is ignored. */
bool TrilinearFilter:1;
//! Magnification (upscaling) filter
E_TEXTURE_MAG_FILTER MagFilter;
//! Is anisotropic filtering enabled? Default: 0, disabled
/** In Irrlicht you can use anisotropic texture filtering
@ -208,6 +230,16 @@ namespace video
if the value is positive. */
s8 LODBias;
//! Sets the MinFilter, MagFilter and AnisotropicFilter properties according
//! to the three relevant boolean values found in the Minetest settings.
/** The value of `trilinear` takes precedence over the value of `bilinear`. */
void setFiltersMinetest(bool bilinear, bool trilinear, bool anisotropic) {
MinFilter = trilinear ? ETMINF_TRILINEAR :
(bilinear ? ETMINF_BILINEAR : ETMINF_NEAREST);
MagFilter = (trilinear || bilinear) ? ETMAGF_BILINEAR : ETMAGF_NEAREST;
AnisotropicFilter = anisotropic ? 0xFF : 0;
}
private:
friend class SMaterial;

@ -104,21 +104,21 @@ namespace video
case EMF_ZWRITE_ENABLE: material.ZWriteEnable = Material.ZWriteEnable; break;
case EMF_BACK_FACE_CULLING: material.BackfaceCulling = Material.BackfaceCulling; break;
case EMF_FRONT_FACE_CULLING: material.FrontfaceCulling = Material.FrontfaceCulling; break;
case EMF_BILINEAR_FILTER:
case EMF_MIN_FILTER:
for ( u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
if ( EnableLayerFlags[i] )
{
material.TextureLayer[i].BilinearFilter = Material.TextureLayer[i].BilinearFilter;
material.TextureLayer[i].MinFilter = Material.TextureLayer[i].MinFilter;
}
}
break;
case EMF_TRILINEAR_FILTER:
case EMF_MAG_FILTER:
for ( u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
if ( EnableLayerFlags[i] )
{
material.TextureLayer[i].TrilinearFilter = Material.TextureLayer[i].TrilinearFilter;
material.TextureLayer[i].MagFilter = Material.TextureLayer[i].MagFilter;
}
}
break;

@ -97,19 +97,19 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& scre
for (u32 i=0; i<video::EVDF_COUNT; ++i)
FeatureEnabled[i]=true;
InitMaterial2D.AntiAliasing=video::EAAM_OFF;
InitMaterial2D.Lighting=false;
InitMaterial2D.ZWriteEnable=video::EZW_OFF;
InitMaterial2D.ZBuffer=video::ECFN_DISABLED;
InitMaterial2D.UseMipMaps=false;
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
{
InitMaterial2D.TextureLayer[i].BilinearFilter=false;
InitMaterial2D.TextureLayer[i].TextureWrapU=video::ETC_REPEAT;
InitMaterial2D.TextureLayer[i].TextureWrapV=video::ETC_REPEAT;
InitMaterial2D.TextureLayer[i].TextureWrapW = video::ETC_REPEAT;
}
OverrideMaterial2D=InitMaterial2D;
InitMaterial2D.AntiAliasing = video::EAAM_OFF;
InitMaterial2D.Lighting = false;
InitMaterial2D.ZWriteEnable = video::EZW_OFF;
InitMaterial2D.ZBuffer = video::ECFN_DISABLED;
InitMaterial2D.UseMipMaps = false;
InitMaterial2D.forEachTexture([] (auto &tex) {
tex.MinFilter = video::ETMINF_NEAREST;
tex.MagFilter = video::ETMAGF_NEAREST;
tex.TextureWrapU = video::ETC_REPEAT;
tex.TextureWrapV = video::ETC_REPEAT;
tex.TextureWrapW = video::ETC_REPEAT;
});
OverrideMaterial2D = InitMaterial2D;
}

@ -1696,41 +1696,40 @@ COGLES2Driver::~COGLES2Driver()
if (resetAllRenderstates)
tmpTexture->getStatesCache().IsCached = false;
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MagFilter != tmpTexture->getStatesCache().MagFilter)
{
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayer[i].MagFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
magFilter == ETMAGF_BILINEAR ? GL_LINEAR : GL_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MagFilter = magFilter;
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
!tmpTexture->getStatesCache().MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
minFilter == ETMINF_TRILINEAR ? GL_LINEAR_MIPMAP_LINEAR :
minFilter == ETMINF_BILINEAR ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MinFilter = minFilter;
tmpTexture->getStatesCache().MipMapStatus = true;
}
}
else
{
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
tmpTexture->getStatesCache().MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
(minFilter == ETMINF_TRILINEAR || minFilter == ETMINF_BILINEAR) ? GL_LINEAR : GL_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MinFilter = minFilter;
tmpTexture->getStatesCache().MipMapStatus = false;
}
}

@ -1914,41 +1914,40 @@ void COGLES1Driver::setTextureRenderStates(const SMaterial& material, bool reset
}
#endif
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter)
if (!statesCache.IsCached || material.TextureLayer[i].MagFilter != statesCache.MagFilter)
{
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayer[i].MagFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
magFilter == ETMAGF_BILINEAR ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MagFilter = magFilter;
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || !statesCache.MipMapStatus)
if (!statesCache.IsCached || material.TextureLayer[i].MinFilter != statesCache.MinFilter ||
!statesCache.MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
minFilter == ETMINF_TRILINEAR ? GL_LINEAR_MIPMAP_LINEAR :
minFilter == ETMINF_BILINEAR ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MinFilter = minFilter;
statesCache.MipMapStatus = true;
}
}
else
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || statesCache.MipMapStatus)
if (!statesCache.IsCached || material.TextureLayer[i].MinFilter != statesCache.MinFilter ||
statesCache.MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
(minFilter == ETMINF_TRILINEAR || minFilter == ETMINF_BILINEAR) ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MinFilter = minFilter;
statesCache.MipMapStatus = false;
}
}

@ -31,8 +31,8 @@ public:
struct SStatesCache
{
SStatesCache() : WrapU(ETC_REPEAT), WrapV(ETC_REPEAT), WrapW(ETC_REPEAT),
LODBias(0), AnisotropicFilter(0), BilinearFilter(false), TrilinearFilter(false),
MipMapStatus(false), IsCached(false)
LODBias(0), AnisotropicFilter(0), MinFilter(video::ETMINF_NEAREST),
MagFilter(video::ETMAGF_NEAREST), MipMapStatus(false), IsCached(false)
{
}
@ -41,8 +41,8 @@ public:
u8 WrapW;
s8 LODBias;
u8 AnisotropicFilter;
bool BilinearFilter;
bool TrilinearFilter;
video::E_TEXTURE_MIN_FILTER MinFilter;
video::E_TEXTURE_MAG_FILTER MagFilter;
bool MipMapStatus;
bool IsCached;
};

@ -2709,41 +2709,40 @@ void COpenGLDriver::setTextureRenderStates(const SMaterial& material, bool reset
}
#endif
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter)
if (!statesCache.IsCached || material.TextureLayer[i].MagFilter != statesCache.MagFilter)
{
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayer[i].MagFilter;
glTexParameteri(tmpType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
magFilter == ETMAGF_BILINEAR ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MagFilter = magFilter;
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || !statesCache.MipMapStatus)
if (!statesCache.IsCached || material.TextureLayer[i].MinFilter != statesCache.MinFilter ||
!statesCache.MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
minFilter == ETMINF_TRILINEAR ? GL_LINEAR_MIPMAP_LINEAR :
minFilter == ETMINF_BILINEAR ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MinFilter = minFilter;
statesCache.MipMapStatus = true;
}
}
else
{
if (!statesCache.IsCached || material.TextureLayer[i].BilinearFilter != statesCache.BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != statesCache.TrilinearFilter || statesCache.MipMapStatus)
if (!statesCache.IsCached || material.TextureLayer[i].MinFilter != statesCache.MinFilter ||
statesCache.MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpType, GL_TEXTURE_MIN_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
(minFilter == ETMINF_TRILINEAR || minFilter == ETMINF_BILINEAR) ? GL_LINEAR : GL_NEAREST);
statesCache.BilinearFilter = material.TextureLayer[i].BilinearFilter;
statesCache.TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
statesCache.MinFilter = minFilter;
statesCache.MipMapStatus = false;
}
}

@ -1456,41 +1456,40 @@ COpenGL3DriverBase::~COpenGL3DriverBase()
if (resetAllRenderstates)
tmpTexture->getStatesCache().IsCached = false;
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MagFilter != tmpTexture->getStatesCache().MagFilter)
{
E_TEXTURE_MAG_FILTER magFilter = material.TextureLayer[i].MagFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
magFilter == ETMAGF_BILINEAR ? GL_LINEAR : GL_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MagFilter = magFilter;
}
if (material.UseMipMaps && tmpTexture->hasMipMaps())
{
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
!tmpTexture->getStatesCache().MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :
material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :
minFilter == ETMINF_TRILINEAR ? GL_LINEAR_MIPMAP_LINEAR :
minFilter == ETMINF_BILINEAR ? GL_LINEAR_MIPMAP_NEAREST :
GL_NEAREST_MIPMAP_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MinFilter = minFilter;
tmpTexture->getStatesCache().MipMapStatus = true;
}
}
else
{
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||
material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)
if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].MinFilter != tmpTexture->getStatesCache().MinFilter ||
tmpTexture->getStatesCache().MipMapStatus)
{
E_TEXTURE_MIN_FILTER minFilter = material.TextureLayer[i].MinFilter;
glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,
(material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);
(minFilter == ETMINF_TRILINEAR || minFilter == ETMINF_BILINEAR) ? GL_LINEAR : GL_NEAREST);
tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;
tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;
tmpTexture->getStatesCache().MinFilter = minFilter;
tmpTexture->getStatesCache().MipMapStatus = false;
}
}