From 95d60083328e88ecfe001c3842342019dcc0835f Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Wed, 26 Mar 2025 18:32:23 +0100 Subject: [PATCH] IrrlichtMt: Fix orientation of IRenderTarget-textures (#15932) Textures created through a render target are flipped along the X axis. For the same reason, screenshots must be flipped back as well ('IVideoDriver::createScreenShot'). This commit implements the same flipping concept in two places: 1. Batch rendering of images (mostly used by fonts/text) 2. In-world rendering of such textures --- irr/src/OpenGL/Driver.cpp | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/irr/src/OpenGL/Driver.cpp b/irr/src/OpenGL/Driver.cpp index 2f6a3ebdf..e83a5b3ec 100644 --- a/irr/src/OpenGL/Driver.cpp +++ b/irr/src/OpenGL/Driver.cpp @@ -867,21 +867,25 @@ void COpenGL3DriverBase::draw2DImageBatch(const video::ITexture *texture, std::vector vtx; vtx.reserve(drawCount * 4); + // texcoords need to be flipped horizontally for RTTs + const bool isRTT = texture->isRenderTarget(); + const core::dimension2du ss = texture->getOriginalSize(); + const f32 invW = 1.f / static_cast(ss.Width); + const f32 invH = 1.f / static_cast(ss.Height); + for (u32 i = 0; i < drawCount; i++) { - core::position2d targetPos = positions[i]; - core::position2d sourcePos = sourceRects[i].UpperLeftCorner; - // This needs to be signed as it may go negative. - core::dimension2d sourceSize(sourceRects[i].getSize()); + const core::position2d targetPos = positions[i]; + const core::rect sourceRect = sourceRects[i]; // now draw it. - core::rect tcoords; - tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width; - tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height; - tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width); - tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height); + const core::rect tcoords( + sourceRect.UpperLeftCorner.X * invW, + (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH, + sourceRect.LowerRightCorner.X * invW, + (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) * invH); - const core::rect poss(targetPos, sourceSize); + const core::rect poss(targetPos, sourceRect.getSize()); f32 left = (f32)poss.UpperLeftCorner.X; f32 right = (f32)poss.LowerRightCorner.X; @@ -1084,6 +1088,14 @@ ITexture *COpenGL3DriverBase::createDeviceDependentTextureCubemap(const io::path return texture; } +// Same as COpenGLDriver::TextureFlipMatrix +static const core::matrix4 s_texture_flip_matrix = { + 1, 0, 0, 0, + 0, -1, 0, 0, + 0, 1, 1, 0, + 0, 0, 0, 1 +}; + //! Sets a material. void COpenGL3DriverBase::setMaterial(const SMaterial &material) { @@ -1094,7 +1106,11 @@ void COpenGL3DriverBase::setMaterial(const SMaterial &material) auto *texture = material.getTexture(i); CacheHandler->getTextureCache().set(i, texture); if (texture) { - setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), material.getTextureMatrix(i)); + setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), + texture->isRenderTarget() + ? material.getTextureMatrix(i) * s_texture_flip_matrix + : material.getTextureMatrix(i) + ); } } }