From 5ececc7d29eedffb0539e50e4cafd9f21af9c2d1 Mon Sep 17 00:00:00 2001 From: Gregor Parzefall Date: Fri, 23 Jun 2023 13:58:50 +0200 Subject: [PATCH] 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. --- include/EMaterialFlags.h | 8 ++--- include/SMaterial.h | 1 - include/SMaterialLayer.h | 54 ++++++++++++++++++++++------ include/SOverrideMaterial.h | 8 ++--- source/Irrlicht/CNullDriver.cpp | 26 +++++++------- source/Irrlicht/COGLES2Driver.cpp | 31 ++++++++-------- source/Irrlicht/COGLESDriver.cpp | 31 ++++++++-------- source/Irrlicht/COpenGLCoreTexture.h | 8 ++--- source/Irrlicht/COpenGLDriver.cpp | 31 ++++++++-------- source/Irrlicht/OpenGL/Driver.cpp | 31 ++++++++-------- 10 files changed, 128 insertions(+), 101 deletions(-) diff --git a/include/EMaterialFlags.h b/include/EMaterialFlags.h index c2ebdee..2449f2a 100644 --- a/include/EMaterialFlags.h +++ b/include/EMaterialFlags.h @@ -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, diff --git a/include/SMaterial.h b/include/SMaterial.h index 3caf2b4..169be15 100644 --- a/include/SMaterial.h +++ b/include/SMaterial.h @@ -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 diff --git a/include/SMaterialLayer.h b/include/SMaterialLayer.h index 8f562de..9c93f60 100644 --- a/include/SMaterialLayer.h +++ b/include/SMaterialLayer.h @@ -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; diff --git a/include/SOverrideMaterial.h b/include/SOverrideMaterial.h index 8ecbae2..3045016 100644 --- a/include/SOverrideMaterial.h +++ b/include/SOverrideMaterial.h @@ -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& scre for (u32 i=0; igetStatesCache().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; } } diff --git a/source/Irrlicht/COGLESDriver.cpp b/source/Irrlicht/COGLESDriver.cpp index 887e293..2c4946c 100644 --- a/source/Irrlicht/COGLESDriver.cpp +++ b/source/Irrlicht/COGLESDriver.cpp @@ -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; } } diff --git a/source/Irrlicht/COpenGLCoreTexture.h b/source/Irrlicht/COpenGLCoreTexture.h index 15a827e..9752c47 100644 --- a/source/Irrlicht/COpenGLCoreTexture.h +++ b/source/Irrlicht/COpenGLCoreTexture.h @@ -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; }; diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index c6197ce..8f731f3 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -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; } } diff --git a/source/Irrlicht/OpenGL/Driver.cpp b/source/Irrlicht/OpenGL/Driver.cpp index a713099..7d123ac 100644 --- a/source/Irrlicht/OpenGL/Driver.cpp +++ b/source/Irrlicht/OpenGL/Driver.cpp @@ -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; } }