diff --git a/include/EMaterialFlags.h b/include/EMaterialFlags.h index c2ebdee3..2449f2a0 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 3caf2b48..169be152 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 8f562deb..9c93f604 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 8ecbae25..3045016d 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 887e293c..2c4946c8 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 15a827e9..9752c475 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 c6197ce8..8f731f3e 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 a7130995..7d123acd 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; } }