diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp index 6f0d3aff..15556183 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramBuilder.cpp @@ -958,6 +958,9 @@ public: "uniform lowp vec2 uTexClampEn0; \n" "uniform lowp vec2 uTexClampEn1; \n" "uniform highp vec2 uTexCoordOffset; \n" + "uniform lowp int uUseTexCoordBounds; \n" + "uniform highp vec4 uTexCoordBounds0; \n" + "uniform highp vec4 uTexCoordBounds1; \n" "uniform lowp int uScreenSpaceTriangle; \n" "highp vec2 texCoord0; \n" "highp vec2 texCoord1; \n" @@ -2595,6 +2598,10 @@ public: " highp vec2 mTexCoord1 = vTexCoord1 + vec2(0.0001); \n" " mTexCoord0 += uTexCoordOffset; \n" " mTexCoord1 += uTexCoordOffset; \n" + " if (uUseTexCoordBounds != 0) { \n" + " mTexCoord0 = clamp(mTexCoord0, uTexCoordBounds0.xy, uTexCoordBounds0.zw); \n" + " mTexCoord1 = clamp(mTexCoord1, uTexCoordBounds1.xy, uTexCoordBounds1.zw); \n" + " } \n" ; } }; diff --git a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp index 241c4859..160f093e 100644 --- a/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp +++ b/src/Graphics/OpenGLContext/GLSL/glsl_CombinerProgramUniformFactory.cpp @@ -1,3 +1,4 @@ +#include #include #include "glsl_CombinerProgramUniformFactory.h" #include @@ -221,11 +222,15 @@ public: URasterInfo(GLuint _program) { LocateUniform(uVertexOffset); LocateUniform(uTexCoordOffset); + LocateUniform(uUseTexCoordBounds); + LocateUniform(uTexCoordBounds0); + LocateUniform(uTexCoordBounds1); } void update(bool _force) override { const bool isNativeRes = config.frameBufferEmulation.nativeResFactor == 1 && config.video.multisampling == 0; const bool isTexRect = dwnd().getDrawer().getDrawingState() == DrawingState::TexRect; + const bool useTexCoordBounds = isTexRect && !isNativeRes; float scale[2] = { 0.0f, 0.0f }; if (config.frameBufferEmulation.nativeResFactor != 0) { scale[0] = scale[1] = static_cast(config.frameBufferEmulation.nativeResFactor); @@ -250,14 +255,68 @@ public: texCoordOffset[1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? -0.5f / scale[1] : -1.0f + 0.5f / scale[1]) * gDP.lastTexRectInfo.dtdy; } } + float tcbounds[2][4] = {}; + if (useTexCoordBounds) { + f32 uls, lrs, ult, lrt, S, T, shiftScaleS, shiftScaleT; + s16 shiftedS, shiftedT; + u32 shifts, shiftt; + for (int t = 0; t < 2; t++) { + const CachedTexture * _pTexture = textureCache().current[t]; + const gDPTile * _pTile = gSP.textureTile[t]; + if (_pTexture != nullptr && _pTile != nullptr){ + if (_pTile->shifts > 10) { + shifts = 16 - _pTile->shifts; + shiftedS = static_cast(gDP.lastTexRectInfo.s << shifts); + shiftScaleS = static_cast(1 << shifts); + } else { + shifts = _pTile->shifts; + shiftedS = static_cast(gDP.lastTexRectInfo.s >> shifts); + shiftScaleS = 1.0f / static_cast(1 << shifts); + } + if (_pTile->shiftt > 10) { + shiftt = 16 - _pTile->shiftt; + shiftedT = static_cast(gDP.lastTexRectInfo.t << shiftt); + shiftScaleT = static_cast(1 << shiftt); + } else { + shiftt = _pTile->shiftt; + shiftedT = static_cast(gDP.lastTexRectInfo.t >> shiftt); + shiftScaleT = 1.0f / static_cast(1 << shiftt); + } + + S = _FIXED2FLOAT(shiftedS, 5); + T = _FIXED2FLOAT(shiftedT, 5); + uls = S + (ceilf(gDP.lastTexRectInfo.ulx) - gDP.lastTexRectInfo.ulx) * gDP.lastTexRectInfo.dsdx * shiftScaleS; + lrs = S + (ceilf(gDP.lastTexRectInfo.lrx) - gDP.lastTexRectInfo.ulx - 1.0f) * gDP.lastTexRectInfo.dsdx * shiftScaleS; + ult = T + (ceilf(gDP.lastTexRectInfo.uly) - gDP.lastTexRectInfo.uly) * gDP.lastTexRectInfo.dtdy * shiftScaleT; + lrt = T + (ceilf(gDP.lastTexRectInfo.lry) - gDP.lastTexRectInfo.uly - 1.0f) * gDP.lastTexRectInfo.dtdy * shiftScaleT; + + tcbounds[t][0] = (fmin(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS; + tcbounds[t][1] = (fmin(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT; + tcbounds[t][2] = (fmax(uls, lrs) - _pTile->fuls) * _pTexture->hdRatioS; + tcbounds[t][3] = (fmax(ult, lrt) - _pTile->fult) * _pTexture->hdRatioT; + if (_pTexture->frameBufferTexture != CachedTexture::fbNone) { + tcbounds[t][0] += _pTexture->offsetS * _pTexture->hdRatioS; + tcbounds[t][1] += _pTexture->offsetT * _pTexture->hdRatioT; + tcbounds[t][2] += _pTexture->offsetS * _pTexture->hdRatioS; + tcbounds[t][3] += _pTexture->offsetT * _pTexture->hdRatioT; + } + } + } + } uVertexOffset.set(vertexOffset, vertexOffset, _force); uTexCoordOffset.set(texCoordOffset[0], texCoordOffset[1], _force); + uUseTexCoordBounds.set(useTexCoordBounds ? 1 : 0, _force); + uTexCoordBounds0.set(tcbounds[0], _force); + uTexCoordBounds1.set(tcbounds[1], _force); } private: fv2Uniform uVertexOffset; fv2Uniform uTexCoordOffset; + iUniform uUseTexCoordBounds; + fv4Uniform uTexCoordBounds0; + fv4Uniform uTexCoordBounds1; }; class UFrameBufferInfo : public UniformGroup