Workaround for graphics glitch in Phantasy Star Portable 2

This commit is contained in:
level99procrastinator 2014-11-08 20:31:17 +08:00
parent 47b731b882
commit a98980d28b
4 changed files with 45 additions and 3 deletions

View File

@ -444,6 +444,7 @@ static ConfigSetting graphicsSettings[] = {
ConfigSetting("VSyncInterval", &g_Config.bVSync, false),
ReportedConfigSetting("DisableStencilTest", &g_Config.bDisableStencilTest, false),
ReportedConfigSetting("AlwaysDepthWrite", &g_Config.bAlwaysDepthWrite, false),
ReportedConfigSetting("DepthRangeHack", &g_Config.bDepthRangeHack, false),
// Not really a graphics setting...
ReportedConfigSetting("TimerHack", &g_Config.bTimerHack, &DefaultTimerHack),

View File

@ -165,6 +165,7 @@ public:
bool bReloadCheats;
bool bDisableStencilTest;
bool bAlwaysDepthWrite;
bool bDepthRangeHack;
bool bTimerHack;
bool bAlphaMaskHack;
bool bBlockTransferGPU;

View File

@ -805,9 +805,46 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
float zScale = getFloat24(gstate.viewportz1) / 65535.0f;
float zOff = getFloat24(gstate.viewportz2) / 65535.0f;
float depthRangeMin = zOff - zScale;
float depthRangeMax = zOff + zScale;
glstate.depthRange.set(depthRangeMin, depthRangeMax);
// In Phantasy Star Portable 2, depth range sometimes goes negative and is clamped by glDepthRange to 0,
// causing graphics clipping glitch (issue #1788). This hack modifies the projection matrix to work around it.
if (g_Config.bDepthRangeHack) {
// if far depth range < 0
if (zOff + zScale < 0.0f) {
// if perspective projection
if (gstate.projMatrix[11] < 0.0f) {
float depthMax = gstate.getDepthRangeMax() / 65535.0f;
float depthMin = gstate.getDepthRangeMin() / 65535.0f;
float a = gstate.projMatrix[10];
float b = gstate.projMatrix[14];
float n = b / (a - 1.0f);
float f = b / (a + 1.0f);
f = (n * f) / (n + ((zOff + zScale) * (n - f) / (depthMax - depthMin)));
a = (n + f) / (n - f);
b = (2.0f * n * f) / (n - f);
gstate.projMatrix[10] = a;
gstate.projMatrix[14] = b;
shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
zOff = (zOff - zScale) / 2.0f;
zScale = -zOff;
gstate.viewportz2 &= 0xFF000000;
gstate.viewportz2 |= toFloat24(zOff * 65535.0f);
gstate.viewportz1 &= 0xFF000000;
gstate.viewportz1 |= toFloat24(zScale * 65535.0f);
}
}
}
glstate.depthRange.set(zOff - zScale, zOff + zScale);
}
}

View File

@ -278,6 +278,9 @@ void GameSettingsScreen::CreateViews() {
CheckBox *prescale = graphicsSettings->Add(new CheckBox(&g_Config.bPrescaleUV, gs->T("Texture Coord Speedhack")));
prescale->SetDisabledPtr(&g_Config.bSoftwareRendering);
CheckBox *depthRange = graphicsSettings->Add(new CheckBox(&g_Config.bDepthRangeHack, gs->T("Depth Range Hack (Phantasy Star Portable 2)")));
depthRange->SetDisabledPtr(&g_Config.bSoftwareRendering);
graphicsSettings->Add(new ItemHeader(gs->T("Overlay Information")));
static const char *fpsChoices[] = {
"None", "Speed", "FPS", "Both"