1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Apply a vertex position or texture coordinate shift to approximate N64 rasterization rules

This commit is contained in:
s2s 2021-03-05 18:42:30 +01:00 committed by Sergey Lipskiy
parent 39153304e1
commit acf26e613d
6 changed files with 84 additions and 19 deletions

View File

@ -267,6 +267,7 @@ public:
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
m_part = ss.str();
}
m_part += "uniform lowp vec2 uVertexOffset; \n";
}
};
@ -512,6 +513,7 @@ public:
m_part = " gl_Position.z /= 8.0; \n";
}
m_part +=
" gl_Position.xy += uVertexOffset * vec2(gl_Position.w); \n"
" gl_Position.zw *= vec2(1024.0f); \n"
"} \n"
;
@ -955,6 +957,7 @@ public:
"uniform lowp vec2 uTexMirrorEn1; \n"
"uniform lowp vec2 uTexClampEn0; \n"
"uniform lowp vec2 uTexClampEn1; \n"
"uniform highp vec2 uTexCoordOffset; \n"
"uniform lowp int uScreenSpaceTriangle; \n"
"highp vec2 texCoord0; \n"
"highp vec2 texCoord1; \n"
@ -2584,6 +2587,19 @@ public:
};
class ShaderFragmentCorrectTexCoords : public ShaderPart {
public:
ShaderFragmentCorrectTexCoords() {
m_part +=
" highp vec2 mTexCoord0 = vTexCoord0 + vec2(0.0001); \n"
" highp vec2 mTexCoord1 = vTexCoord1 + vec2(0.0001); \n"
" mTexCoord0 += uTexCoordOffset; \n"
" mTexCoord1 += uTexCoordOffset; \n"
;
}
};
class ShaderTextureEngine : public ShaderPart
{
public:
@ -2646,7 +2662,7 @@ public:
ShaderFragmentTextureEngineTex0(const opengl::GLInfo _glinfo)
{
m_part =
"textureEngine0(vTexCoord0, tcData0); \n"
"textureEngine0(mTexCoord0, tcData0); \n"
;
}
};
@ -2656,7 +2672,7 @@ public:
ShaderFragmentTextureEngineTex1(const opengl::GLInfo _glinfo)
{
m_part =
"textureEngine1(vTexCoord1, tcData1); \n"
"textureEngine1(mTexCoord1, tcData1); \n"
;
}
};
@ -2900,6 +2916,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
if (bUseTextures) {
m_fragmentCorrectTexCoords->write(ssShader);
if (combinerInputs.usesTile(0))
{
m_fragmentTextureEngineTex0->write(ssShader);
@ -3069,6 +3086,7 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
, m_fragmentCorrectTexCoords(new ShaderFragmentCorrectTexCoords())
, m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo))
, m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo))
, m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo))

View File

@ -74,6 +74,7 @@ namespace glsl {
ShaderPartPtr m_fragmentBlendMux;
ShaderPartPtr m_fragmentReadTex0;
ShaderPartPtr m_fragmentReadTex1;
ShaderPartPtr m_fragmentCorrectTexCoords;
ShaderPartPtr m_fragmentTextureEngineTex0;
ShaderPartPtr m_fragmentTextureEngineTex1;
ShaderPartPtr m_fragmentReadTexCopyMode;

View File

@ -216,6 +216,50 @@ private:
iUniform uScreenSpaceTriangle;
};
class URasterInfo : public UniformGroup {
public:
URasterInfo(GLuint _program) {
LocateUniform(uVertexOffset);
LocateUniform(uTexCoordOffset);
}
void update(bool _force) override {
const bool isNativeRes = config.frameBufferEmulation.nativeResFactor == 1 && config.video.multisampling == 0;
const bool isTexRect = dwnd().getDrawer().getDrawingState() == DrawingState::TexRect;
float scale[2] = { 0.0f, 0.0f };
if (config.frameBufferEmulation.nativeResFactor != 0) {
scale[0] = scale[1] = static_cast<float>(config.frameBufferEmulation.nativeResFactor);
} else {
scale[0] = dwnd().getScaleX();
scale[1] = dwnd().getScaleY();
}
/* At rasterization stage, the N64 places samples on the top left of the fragment while OpenGL */
/* places them in the fragment center. As a result, a normal approach results in shifted texture */
/* coordinates. In native resolution, this difference can be negated by shifting vertices by 0.5. */
/* In higher resolutions, there are more samples than the game intends, so shifting is not very */
/* effective. Still, an heuristic is applied to render texture rectangles as correctly as possible */
/* in higher resolutions too. See issue #2324 for details. */
const float vertexOffset = isNativeRes ? 0.5f : 0.0f;
float texCoordOffset[2] = { 0.0f, 0.0f };
if (isTexRect && !isNativeRes) {
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texCoordOffset[0] = -0.5f * gDP.lastTexRectInfo.dsdx;
texCoordOffset[1] = -0.5f * gDP.lastTexRectInfo.dtdy;
} else {
texCoordOffset[0] = (gDP.lastTexRectInfo.dsdx >= 0.0f ? -0.5f / scale[0] : -1.0f + 0.5f / scale[0]) * gDP.lastTexRectInfo.dsdx;
texCoordOffset[1] = (gDP.lastTexRectInfo.dtdy >= 0.0f ? -0.5f / scale[1] : -1.0f + 0.5f / scale[1]) * gDP.lastTexRectInfo.dtdy;
}
}
uVertexOffset.set(vertexOffset, vertexOffset, _force);
uTexCoordOffset.set(texCoordOffset[0], texCoordOffset[1], _force);
}
private:
fv2Uniform uVertexOffset;
fv2Uniform uTexCoordOffset;
};
class UFrameBufferInfo : public UniformGroup
{
public:
@ -1115,6 +1159,7 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
{
_uniforms.emplace_back(new UNoiseTex(_program));
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
_uniforms.emplace_back(new URasterInfo(_program));
_uniforms.emplace_back(new UViewportInfo(_program));
if (!m_glInfo.isGLES2) {

View File

@ -1315,15 +1315,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
texST[t].t0 = ult - gSP.textureTile[t]->fult;
texST[t].t1 = lrt - gSP.textureTile[t]->fult;
if (uls > lrs) {
texST[t].s0 -= _params.dsdx * shiftScaleS;
texST[t].s1 -= _params.dsdx * shiftScaleS;
}
if (ult > lrt) {
texST[t].t0 -= _params.dtdy * shiftScaleT;
texST[t].t1 -= _params.dtdy * shiftScaleT;
}
if (cache.current[t]->frameBufferTexture != CachedTexture::fbNone) {
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
texST[t].t0 = cache.current[t]->offsetT + texST[t].t0;
@ -1360,13 +1351,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
texST[t].s1 *= cache.current[t]->hdRatioS;
texST[t].t1 *= cache.current[t]->hdRatioT;
if (gDP.otherMode.textureFilter != G_TF_POINT && gDP.otherMode.cycleType != G_CYC_COPY) {
texST[t].s0 -= 0.5f;
texST[t].t0 -= 0.5f;
texST[t].s1 -= 0.5f;
texST[t].t1 -= 0.5f;
}
}
}

View File

@ -866,6 +866,15 @@ void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s1
gDP.rectColor = gDPInfo::Color();
gDP.lastTexRectInfo.ulx = ulx;
gDP.lastTexRectInfo.lrx = lrx;
gDP.lastTexRectInfo.uly = uly;
gDP.lastTexRectInfo.lry = lry;
gDP.lastTexRectInfo.s = !flip ? s : t;
gDP.lastTexRectInfo.t = !flip ? t : s;
gDP.lastTexRectInfo.dsdx = !flip ? dsdx : dtdy;
gDP.lastTexRectInfo.dtdy = !flip ? dtdy : dsdx;
GraphicsDrawer & drawer = dwnd().getDrawer();
GraphicsDrawer::TexturedRectParams params(ulx, uly, lrx, lry, dsdx, dtdy, s, t,
flip, false, true, frameBufferList().getCurrent());

View File

@ -122,6 +122,13 @@ struct gDPScissor
s16 xh, yh, xl, yl;
};
struct gDPTexrectInfo
{
f32 ulx, lrx, uly, lry;
s16 s, t;
f32 dsdx, dtdy;
};
struct gDPInfo
{
struct OtherMode
@ -255,7 +262,8 @@ struct gDPInfo
u64 paletteCRC256;
u32 half_1, half_2;
gDPLoadTileInfo loadInfo[512];
gDPLoadTileInfo loadInfo[512];
gDPTexrectInfo lastTexRectInfo;
};
extern gDPInfo gDP;