mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
Apply a vertex position or texture coordinate shift to approximate N64 rasterization rules
This commit is contained in:
parent
39153304e1
commit
acf26e613d
|
@ -267,6 +267,7 @@ public:
|
||||||
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
|
ss << "# define IN in" << std::endl << "# define OUT out" << std::endl;
|
||||||
m_part = ss.str();
|
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.z /= 8.0; \n";
|
||||||
}
|
}
|
||||||
m_part +=
|
m_part +=
|
||||||
|
" gl_Position.xy += uVertexOffset * vec2(gl_Position.w); \n"
|
||||||
" gl_Position.zw *= vec2(1024.0f); \n"
|
" gl_Position.zw *= vec2(1024.0f); \n"
|
||||||
"} \n"
|
"} \n"
|
||||||
;
|
;
|
||||||
|
@ -955,6 +957,7 @@ public:
|
||||||
"uniform lowp vec2 uTexMirrorEn1; \n"
|
"uniform lowp vec2 uTexMirrorEn1; \n"
|
||||||
"uniform lowp vec2 uTexClampEn0; \n"
|
"uniform lowp vec2 uTexClampEn0; \n"
|
||||||
"uniform lowp vec2 uTexClampEn1; \n"
|
"uniform lowp vec2 uTexClampEn1; \n"
|
||||||
|
"uniform highp vec2 uTexCoordOffset; \n"
|
||||||
"uniform lowp int uScreenSpaceTriangle; \n"
|
"uniform lowp int uScreenSpaceTriangle; \n"
|
||||||
"highp vec2 texCoord0; \n"
|
"highp vec2 texCoord0; \n"
|
||||||
"highp vec2 texCoord1; \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
|
class ShaderTextureEngine : public ShaderPart
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -2646,7 +2662,7 @@ public:
|
||||||
ShaderFragmentTextureEngineTex0(const opengl::GLInfo _glinfo)
|
ShaderFragmentTextureEngineTex0(const opengl::GLInfo _glinfo)
|
||||||
{
|
{
|
||||||
m_part =
|
m_part =
|
||||||
"textureEngine0(vTexCoord0, tcData0); \n"
|
"textureEngine0(mTexCoord0, tcData0); \n"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2656,7 +2672,7 @@ public:
|
||||||
ShaderFragmentTextureEngineTex1(const opengl::GLInfo _glinfo)
|
ShaderFragmentTextureEngineTex1(const opengl::GLInfo _glinfo)
|
||||||
{
|
{
|
||||||
m_part =
|
m_part =
|
||||||
"textureEngine1(vTexCoord1, tcData1); \n"
|
"textureEngine1(mTexCoord1, tcData1); \n"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2900,6 +2916,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
|
||||||
|
|
||||||
|
|
||||||
if (bUseTextures) {
|
if (bUseTextures) {
|
||||||
|
m_fragmentCorrectTexCoords->write(ssShader);
|
||||||
if (combinerInputs.usesTile(0))
|
if (combinerInputs.usesTile(0))
|
||||||
{
|
{
|
||||||
m_fragmentTextureEngineTex0->write(ssShader);
|
m_fragmentTextureEngineTex0->write(ssShader);
|
||||||
|
@ -3069,6 +3086,7 @@ CombinerProgramBuilder::CombinerProgramBuilder(const opengl::GLInfo & _glinfo, o
|
||||||
, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
|
, m_fragmentBlendMux(new ShaderFragmentBlendMux(_glinfo))
|
||||||
, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
|
, m_fragmentReadTex0(new ShaderFragmentReadTex0(_glinfo))
|
||||||
, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
|
, m_fragmentReadTex1(new ShaderFragmentReadTex1(_glinfo))
|
||||||
|
, m_fragmentCorrectTexCoords(new ShaderFragmentCorrectTexCoords())
|
||||||
, m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo))
|
, m_fragmentTextureEngineTex0(new ShaderFragmentTextureEngineTex0(_glinfo))
|
||||||
, m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo))
|
, m_fragmentTextureEngineTex1(new ShaderFragmentTextureEngineTex1(_glinfo))
|
||||||
, m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo))
|
, m_fragmentReadTexCopyMode(new ShaderFragmentReadTexCopyMode(_glinfo))
|
||||||
|
|
|
@ -74,6 +74,7 @@ namespace glsl {
|
||||||
ShaderPartPtr m_fragmentBlendMux;
|
ShaderPartPtr m_fragmentBlendMux;
|
||||||
ShaderPartPtr m_fragmentReadTex0;
|
ShaderPartPtr m_fragmentReadTex0;
|
||||||
ShaderPartPtr m_fragmentReadTex1;
|
ShaderPartPtr m_fragmentReadTex1;
|
||||||
|
ShaderPartPtr m_fragmentCorrectTexCoords;
|
||||||
ShaderPartPtr m_fragmentTextureEngineTex0;
|
ShaderPartPtr m_fragmentTextureEngineTex0;
|
||||||
ShaderPartPtr m_fragmentTextureEngineTex1;
|
ShaderPartPtr m_fragmentTextureEngineTex1;
|
||||||
ShaderPartPtr m_fragmentReadTexCopyMode;
|
ShaderPartPtr m_fragmentReadTexCopyMode;
|
||||||
|
|
|
@ -216,6 +216,50 @@ private:
|
||||||
iUniform uScreenSpaceTriangle;
|
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
|
class UFrameBufferInfo : public UniformGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -1115,6 +1159,7 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
|
||||||
{
|
{
|
||||||
_uniforms.emplace_back(new UNoiseTex(_program));
|
_uniforms.emplace_back(new UNoiseTex(_program));
|
||||||
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
|
_uniforms.emplace_back(new UScreenSpaceTriangleInfo(_program));
|
||||||
|
_uniforms.emplace_back(new URasterInfo(_program));
|
||||||
_uniforms.emplace_back(new UViewportInfo(_program));
|
_uniforms.emplace_back(new UViewportInfo(_program));
|
||||||
|
|
||||||
if (!m_glInfo.isGLES2) {
|
if (!m_glInfo.isGLES2) {
|
||||||
|
|
|
@ -1315,15 +1315,6 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
|
||||||
texST[t].t0 = ult - gSP.textureTile[t]->fult;
|
texST[t].t0 = ult - gSP.textureTile[t]->fult;
|
||||||
texST[t].t1 = lrt - 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) {
|
if (cache.current[t]->frameBufferTexture != CachedTexture::fbNone) {
|
||||||
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
|
texST[t].s0 = cache.current[t]->offsetS + texST[t].s0;
|
||||||
texST[t].t0 = cache.current[t]->offsetT + texST[t].t0;
|
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].s1 *= cache.current[t]->hdRatioS;
|
||||||
texST[t].t1 *= cache.current[t]->hdRatioT;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -866,6 +866,15 @@ void gDPTextureRectangle(f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, s16 s, s1
|
||||||
|
|
||||||
gDP.rectColor = gDPInfo::Color();
|
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 & drawer = dwnd().getDrawer();
|
||||||
GraphicsDrawer::TexturedRectParams params(ulx, uly, lrx, lry, dsdx, dtdy, s, t,
|
GraphicsDrawer::TexturedRectParams params(ulx, uly, lrx, lry, dsdx, dtdy, s, t,
|
||||||
flip, false, true, frameBufferList().getCurrent());
|
flip, false, true, frameBufferList().getCurrent());
|
||||||
|
|
10
src/gDP.h
10
src/gDP.h
|
@ -122,6 +122,13 @@ struct gDPScissor
|
||||||
s16 xh, yh, xl, yl;
|
s16 xh, yh, xl, yl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gDPTexrectInfo
|
||||||
|
{
|
||||||
|
f32 ulx, lrx, uly, lry;
|
||||||
|
s16 s, t;
|
||||||
|
f32 dsdx, dtdy;
|
||||||
|
};
|
||||||
|
|
||||||
struct gDPInfo
|
struct gDPInfo
|
||||||
{
|
{
|
||||||
struct OtherMode
|
struct OtherMode
|
||||||
|
@ -255,7 +262,8 @@ struct gDPInfo
|
||||||
u64 paletteCRC256;
|
u64 paletteCRC256;
|
||||||
u32 half_1, half_2;
|
u32 half_1, half_2;
|
||||||
|
|
||||||
gDPLoadTileInfo loadInfo[512];
|
gDPLoadTileInfo loadInfo[512];
|
||||||
|
gDPTexrectInfo lastTexRectInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern gDPInfo gDP;
|
extern gDPInfo gDP;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user