mirror of https://github.com/PCSX2/pcsx2.git
gsdx-ogl: alternate implementation of half pixel offset
The previous implementation of HPO adds an offset on vertex position. It doesn't always work beside it moves the rendering window. The new implementation will add a texture offset so that instead to sample the middle of the GS texel, we will sample the middle of the real texture texel. It must be manually enabled with * UserHacks_HalfPixelOffset_New = 1 (keep a small offset as intended by GS effect) * UserHacks_HalfPixelOffset_New = 2 (no offset) v2: always apply a 0.5 offset in case of float coordinates (Tales of Abyss) Might break other games but few of them uses float coordinates to read back the target
This commit is contained in:
parent
c2229e3c0b
commit
61a7c747e1
|
@ -39,6 +39,7 @@ GSRendererOGL::GSRendererOGL()
|
|||
UserHacks_TCO_y = ((UserHacks_TCOffset >> 16) & 0xFFFF) / -1000.0f;
|
||||
UserHacks_merge_sprite = theApp.GetConfigB("UserHacks_merge_pp_sprite");
|
||||
UserHacks_unscale_pt_ln = theApp.GetConfigB("UserHacks_unscale_point_line");
|
||||
UserHacks_HPO = theApp.GetConfigI("UserHacks_HalfPixelOffset_New");
|
||||
|
||||
m_prim_overlap = PRIM_OVERLAP_UNKNOW;
|
||||
ResetStates();
|
||||
|
@ -49,6 +50,7 @@ GSRendererOGL::GSRendererOGL()
|
|||
UserHacks_TCO_y = 0;
|
||||
UserHacks_merge_sprite = false;
|
||||
UserHacks_unscale_pt_ln = false;
|
||||
UserHacks_HPO = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -736,6 +738,59 @@ void GSRendererOGL::EmulateBlending(bool DATE_GL42)
|
|||
}
|
||||
}
|
||||
|
||||
void GSRendererOGL::RealignTargetTextureCoordinate(const GSTextureCache::Source* tex)
|
||||
{
|
||||
if (!UserHacks_HPO || GetUpscaleMultiplier() == 1) return;
|
||||
|
||||
GSVertex* v = &m_vertex.buff[0];
|
||||
const GSVector2& scale = tex->m_texture->GetScale();
|
||||
bool linear = m_vt.IsLinear();
|
||||
int t_position = v[0].U;
|
||||
GSVector4 half_offset(0.0f);
|
||||
|
||||
// FIXME Let's start with something wrong same mess on X and Y
|
||||
// FIXME Maybe it will be enough to check linear
|
||||
|
||||
if (PRIM->FST) {
|
||||
|
||||
if (UserHacks_HPO > 1) {
|
||||
if (!linear && t_position == 8) {
|
||||
half_offset.x = 8;
|
||||
half_offset.y = 8;
|
||||
} else if (linear && t_position == 16) {
|
||||
half_offset.x = 16;
|
||||
half_offset.y = 16;
|
||||
}
|
||||
} else {
|
||||
if (!linear && t_position == 8) {
|
||||
half_offset.x = 8 - 8 / scale.x;
|
||||
half_offset.y = 8 - 8 / scale.y;
|
||||
} else if (linear && t_position == 16) {
|
||||
half_offset.x = 16 - 16 / scale.x;
|
||||
half_offset.y = 16 - 16 / scale.y;
|
||||
}
|
||||
}
|
||||
|
||||
GL_INS("offset detected %f,%f t_pos %d (linear %d, scale %f)",
|
||||
half_offset.x, half_offset.y, t_position, linear, scale.x);
|
||||
|
||||
} else if (m_vt.m_eq.q) {
|
||||
float tw = (float)(1 << m_context->TEX0.TW);
|
||||
float th = (float)(1 << m_context->TEX0.TH);
|
||||
float q = v[0].RGBAQ.Q;
|
||||
|
||||
// Tales of Abyss
|
||||
half_offset.x = 0.5f * q / tw;
|
||||
half_offset.y = 0.5f * q / th;
|
||||
|
||||
GL_INS("ST offset detected %f,%f (linear %d, scale %f)",
|
||||
half_offset.x, half_offset.y, linear, scale.x);
|
||||
|
||||
}
|
||||
|
||||
vs_cb.TextureOffset = GSVector4(half_offset);
|
||||
}
|
||||
|
||||
void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
||||
{
|
||||
GSDeviceOGL* dev = (GSDeviceOGL*)m_dev;
|
||||
|
@ -829,6 +884,8 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
|||
// The purpose of texture shuffle is to move color channel. Extra interpolation is likely a bad idea.
|
||||
bilinear &= m_vt.IsLinear();
|
||||
|
||||
RealignTargetTextureCoordinate(tex);
|
||||
|
||||
} else if (tex->m_target) {
|
||||
// Use an old target. AEM and index aren't resolved it must be done
|
||||
// on the GPU
|
||||
|
@ -877,6 +934,8 @@ void GSRendererOGL::EmulateTextureSampler(const GSTextureCache::Source* tex)
|
|||
bilinear &= m_vt.IsLinear();
|
||||
}
|
||||
|
||||
RealignTargetTextureCoordinate(tex);
|
||||
|
||||
} else if (tex->m_palette) {
|
||||
// Use a standard 8 bits texture. AEM is already done on the CLUT
|
||||
// Therefore you only need to set the index
|
||||
|
@ -1158,6 +1217,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
bool ate_second_pass = m_context->TEST.DoSecondPass();
|
||||
|
||||
ResetStates();
|
||||
vs_cb.TextureOffset = GSVector4(0.0f);
|
||||
|
||||
ASSERT(m_dev != NULL);
|
||||
GSDeviceOGL* dev = (GSDeviceOGL*)m_dev;
|
||||
|
@ -1354,7 +1414,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
//The resulting shifted output aligns better with common blending / corona / blurring effects,
|
||||
//but introduces a few bad pixels on the edges.
|
||||
|
||||
if (rt && rt->LikelyOffset)
|
||||
if (rt && rt->LikelyOffset && !UserHacks_HPO)
|
||||
{
|
||||
ox2 *= rt->OffsetHack_modx;
|
||||
oy2 *= rt->OffsetHack_mody;
|
||||
|
|
|
@ -54,6 +54,7 @@ class GSRendererOGL final : public GSRendererHW
|
|||
float UserHacks_TCO_x, UserHacks_TCO_y;
|
||||
bool UserHacks_merge_sprite;
|
||||
bool UserHacks_unscale_pt_ln;
|
||||
int UserHacks_HPO;
|
||||
|
||||
GSDeviceOGL::VSConstantBuffer vs_cb;
|
||||
GSDeviceOGL::PSConstantBuffer ps_cb;
|
||||
|
@ -75,6 +76,7 @@ class GSRendererOGL final : public GSRendererHW
|
|||
inline void ResetStates();
|
||||
inline void Lines2Sprites();
|
||||
inline void SetupIA(const float& sx, const float& sy);
|
||||
inline void RealignTargetTextureCoordinate(const GSTextureCache::Source* tex);
|
||||
inline void EmulateTextureShuffleAndFbmask();
|
||||
inline void EmulateChannelShuffle(GSTexture** rt, const GSTextureCache::Source* tex);
|
||||
inline void EmulateBlending(bool DATE_GL42);
|
||||
|
|
|
@ -351,6 +351,7 @@ void GSdxApp::Init()
|
|||
m_default_configuration["UserHacks_DisableGsMemClear"] = "0";
|
||||
m_default_configuration["UserHacks_DisablePartialInvalidation"] = "0";
|
||||
m_default_configuration["UserHacks_HalfPixelOffset"] = "0";
|
||||
m_default_configuration["UserHacks_HalfPixelOffset_New"] = "0";
|
||||
m_default_configuration["UserHacks_merge_pp_sprite"] = "0";
|
||||
m_default_configuration["UserHacks_MSAA"] = "0";
|
||||
m_default_configuration["UserHacks_unscale_point_line"] = "0";
|
||||
|
|
|
@ -27,7 +27,7 @@ void texture_coord()
|
|||
vec2 uv = vec2(i_uv) - TextureOffset.xy;
|
||||
|
||||
// Float coordinate
|
||||
VSout.t_float.xy = i_st - TextureOffset.zw; // FIXME or .xy check final code
|
||||
VSout.t_float.xy = i_st - TextureOffset.xy;
|
||||
VSout.t_float.w = i_q;
|
||||
|
||||
// Integer coordinate => normalized
|
||||
|
|
|
@ -770,7 +770,7 @@ static const char* const tfx_vgs_glsl =
|
|||
" vec2 uv = vec2(i_uv) - TextureOffset.xy;\n"
|
||||
"\n"
|
||||
" // Float coordinate\n"
|
||||
" VSout.t_float.xy = i_st - TextureOffset.zw; // FIXME or .xy check final code\n"
|
||||
" VSout.t_float.xy = i_st - TextureOffset.xy;\n"
|
||||
" VSout.t_float.w = i_q;\n"
|
||||
"\n"
|
||||
" // Integer coordinate => normalized\n"
|
||||
|
|
Loading…
Reference in New Issue