From 024e1d2d279ef6be172c0be22fef66f34122ac21 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 4 Sep 2025 18:58:23 +0200 Subject: [PATCH] IrrlichtMt: Implement mip-mapping for RTTs (#16434) This can be helpful to draw fonts memory-efficiently at varying scales. Adds ETCF_CREATE_RTT_MIP_MAPS to generate mip-maps on request. --- irr/include/ITexture.h | 5 +++++ irr/src/CNullDriver.cpp | 12 ++++++++++-- irr/src/COpenGLCoreTexture.h | 27 ++++++++++++++------------- irr/src/COpenGLDriver.cpp | 21 +++++++-------------- irr/src/OpenGL/Driver.cpp | 22 +++++++--------------- 5 files changed, 43 insertions(+), 44 deletions(-) diff --git a/irr/include/ITexture.h b/irr/include/ITexture.h index 21ea319c0a..8c31dc7e96 100644 --- a/irr/include/ITexture.h +++ b/irr/include/ITexture.h @@ -66,6 +66,11 @@ enum E_TEXTURE_CREATION_FLAG not recommended to enable this flag. */ ETCF_NO_ALPHA_CHANNEL = 0x00000020, + /** Creates Render Target Textures with mipmap levels. + See also: `ETCF_CREATE_MIP_MAPS` for other textures. + This is disabled by default. */ + ETCF_CREATE_RTT_MIP_MAPS = 0x00000040, + //! Allow the driver to keep a copy of the texture in memory /** Enabling this makes calls to ITexture::lock a lot faster, but costs main memory. This is disabled by default. diff --git a/irr/src/CNullDriver.cpp b/irr/src/CNullDriver.cpp index 2ef371d89b..6d20d9634a 100644 --- a/irr/src/CNullDriver.cpp +++ b/irr/src/CNullDriver.cpp @@ -84,9 +84,17 @@ CNullDriver::CNullDriver(io::IFileSystem *io, const core::dimension2d &scre InitMaterial2D.AntiAliasing = video::EAAM_OFF; InitMaterial2D.ZWriteEnable = video::EZW_OFF; InitMaterial2D.ZBuffer = video::ECFN_DISABLED; - InitMaterial2D.UseMipMaps = false; - InitMaterial2D.forEachTexture([](auto &tex) { + InitMaterial2D.UseMipMaps = true; + InitMaterial2D.forEachTexture([](video::SMaterialLayer &tex) { + // Best preset for 2D pixel-perfect graphics tex.MinFilter = video::ETMINF_NEAREST_MIPMAP_NEAREST; + + // Best preset for downscaled 2D graphics using trilinear interpolation + //tex.MinFilter = video::ETMINF_LINEAR_MIPMAP_LINEAR; + // Lower bias -> more crisp images, more jitter + // Higher bias -> burry images, less jitter + //tex.LODBias = -1; + tex.MagFilter = video::ETMAGF_NEAREST; tex.TextureWrapU = video::ETC_REPEAT; tex.TextureWrapV = video::ETC_REPEAT; diff --git a/irr/src/COpenGLCoreTexture.h b/irr/src/COpenGLCoreTexture.h index e4a8d996eb..18e40bf6d8 100644 --- a/irr/src/COpenGLCoreTexture.h +++ b/irr/src/COpenGLCoreTexture.h @@ -103,14 +103,6 @@ public: GL.TexParameteri(TextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GL.TexParameteri(TextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (HasMipMaps) { - if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) - GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); - else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) - GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - else - GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); - } TEST_GL_ERROR(Driver); initTexture(tmpImages->size()); @@ -147,7 +139,7 @@ public: DriverType = Driver->getDriverType(); assert(Type != ETT_2D_ARRAY); // not supported by this constructor TextureType = TextureTypeIrrToGL(Type); - HasMipMaps = false; + HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_RTT_MIP_MAPS); IsRenderTarget = true; if (!name.empty()) @@ -189,8 +181,9 @@ public: char lbuf[200]; snprintf_irr(lbuf, sizeof(lbuf), - "COpenGLCoreTexture: RTT Type = %d Size = %dx%d (S:%d) ColorFormat = %s -> %#06x %#06x %#06x%s", + "COpenGLCoreTexture: RTT Type = %d Size = %dx%d (S:%d) ColorFormat = %s%s -> %#06x %#06x %#06x%s", (int)Type, Size.Width, Size.Height, (int)MSAA, ColorFormatName(ColorFormat), + HasMipMaps ? " +Mip" : "", InternalFormat, PixelFormat, PixelType, Converter ? " (c)" : "" ); os::Printer::log(lbuf, ELL_DEBUG); @@ -397,13 +390,21 @@ public: if (!HasMipMaps || (Size.Width <= 1 && Size.Height <= 1)) return; - const COpenGLCoreTexture *prevTexture = Driver->getCacheHandler()->getTextureCache().get(0); - Driver->getCacheHandler()->getTextureCache().set(0, this); + auto &cache = Driver->getCacheHandler()->getTextureCache(); + const COpenGLCoreTexture *prevTexture = cache.get(0); + cache.set(0, this); + + if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) + GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); + else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) + GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + else + GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); Driver->irrGlGenerateMipmap(TextureType); TEST_GL_ERROR(Driver); - Driver->getCacheHandler()->getTextureCache().set(0, prevTexture); + cache.set(0, prevTexture); } GLenum getOpenGLTextureType() const diff --git a/irr/src/COpenGLDriver.cpp b/irr/src/COpenGLDriver.cpp index 6ae4654e18..06348cb36c 100644 --- a/irr/src/COpenGLDriver.cpp +++ b/irr/src/COpenGLDriver.cpp @@ -2614,10 +2614,6 @@ ITexture *COpenGLDriver::addRenderTargetTextureMs(const core::dimension2d & if (IImage::isCompressedFormat(format)) return 0; - // disable mip-mapping - bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); - bool supportForFBO = (Feature.ColorAttachment > 0); core::dimension2du destSize(size); @@ -2631,9 +2627,6 @@ ITexture *COpenGLDriver::addRenderTargetTextureMs(const core::dimension2d & addTexture(renderTargetTexture); renderTargetTexture->drop(); - // restore mip-mapping - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); - return renderTargetTexture; } @@ -2643,10 +2636,6 @@ ITexture *COpenGLDriver::addRenderTargetTextureCubemap(const u32 sideLen, const if (IImage::isCompressedFormat(format)) return 0; - // disable mip-mapping - bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); - bool supportForFBO = (Feature.ColorAttachment > 0); const core::dimension2d size(sideLen, sideLen); @@ -2661,9 +2650,6 @@ ITexture *COpenGLDriver::addRenderTargetTextureCubemap(const u32 sideLen, const addTexture(renderTargetTexture); renderTargetTexture->drop(); - // restore mip-mapping - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); - return renderTargetTexture; } @@ -2682,6 +2668,13 @@ bool COpenGLDriver::setRenderTargetEx(IRenderTarget *target, u16 clearFlag, SCol return false; } + if (CurrentRenderTarget) { + // Update mip-map of the generated texture, if enabled. + auto textures = CurrentRenderTarget->getTexture(); + for (size_t i = 0; i < textures.size(); ++i) + textures[i]->regenerateMipMapLevels(); + } + bool supportForFBO = (Feature.ColorAttachment > 0); core::dimension2d destRenderTargetSize(0, 0); diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp index a03f4d7f35..025eeb269e 100644 --- a/irr/src/OpenGL/Driver.cpp +++ b/irr/src/OpenGL/Driver.cpp @@ -266,7 +266,6 @@ bool COpenGL3DriverBase::genericDriverInit(const core::dimension2d &screenS GL.ClearDepthf(1.0f); - GL.Hint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); GL.FrontFace(GL_CW); // create material renderers @@ -1663,26 +1662,15 @@ ITexture *COpenGL3DriverBase::addRenderTargetTexture(const core::dimension2d &size, u8 msaa, const io::path &name, const ECOLOR_FORMAT format) { - // disable mip-mapping - bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); - COpenGL3Texture *renderTargetTexture = new COpenGL3Texture(name, size, msaa > 0 ? ETT_2D_MS : ETT_2D, format, this, msaa); addTexture(renderTargetTexture); renderTargetTexture->drop(); - // restore mip-mapping - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); - return renderTargetTexture; } ITexture *COpenGL3DriverBase::addRenderTargetTextureCubemap(const u32 sideLen, const io::path &name, const ECOLOR_FORMAT format) { - // disable mip-mapping - bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); - bool supportForFBO = (Feature.ColorAttachment > 0); const core::dimension2d size(sideLen, sideLen); @@ -1697,9 +1685,6 @@ ITexture *COpenGL3DriverBase::addRenderTargetTextureCubemap(const u32 sideLen, c addTexture(renderTargetTexture); renderTargetTexture->drop(); - // restore mip-mapping - setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels); - return renderTargetTexture; } @@ -1716,6 +1701,13 @@ bool COpenGL3DriverBase::setRenderTargetEx(IRenderTarget *target, u16 clearFlag, return false; } + if (CurrentRenderTarget) { + // Update mip-map of the generated texture, if enabled. + auto textures = CurrentRenderTarget->getTexture(); + for (size_t i = 0; i < textures.size(); ++i) + textures[i]->regenerateMipMapLevels(); + } + core::dimension2d destRenderTargetSize(0, 0); if (target) {