Simulate depth clamping.

We'll allow extra space in both directions.  It's not exactly right, but
it's a fast approximation.
This commit is contained in:
Unknown W. Brackets 2016-01-18 20:53:38 -08:00
parent 0920f6c6eb
commit b80c02c272
6 changed files with 39 additions and 16 deletions

View File

@ -498,6 +498,15 @@ LogicOpReplaceType ReplaceLogicOpType() {
return LOGICOPTYPE_NORMAL;
}
static const float depthSliceFactor = 4.0f;
float ToScaledDepth(u16 z) {
return z * (1.0f / depthSliceFactor) * (1.0f / 65535.0f) + (0.5f / depthSliceFactor);
}
float ToScaledDepthFromInteger(float z) {
return z * (1.0f / depthSliceFactor) * (1.0f / 65535.0f) + (0.5f / depthSliceFactor);
}
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) {
bool throughmode = gstate.isModeThrough();
@ -638,14 +647,27 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float minz = gstate.getDepthRangeMin();
float maxz = gstate.getDepthRangeMax();
if (gstate.isClippingEnabled() && (minz == 0 || maxz == 65535)) {
// Here, we should "clamp." But clamping per fragment would be slow.
// So, instead, we just increase the available range and hope.
// If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction.
float fullDepthRange = 65535.0f * (depthSliceFactor - 1.0f) * (1.0f / 2.0f);
if (minz == 0) {
minz -= fullDepthRange;
}
if (maxz == 65535) {
maxz += fullDepthRange;
}
}
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
float halfActualZRange = (maxz - minz) * (1.0f / 2.0f);
float zScale = vpZScale / halfActualZRange;
// This adjusts the center from halfActualZRange to vpZCenter.
float zOffset = (vpZCenter - (minz + halfActualZRange)) / halfActualZRange;
out.depthRangeMin = ToScaledDepth(minz);
out.depthRangeMax = ToScaledDepth(maxz);
out.depthRangeMin = ToScaledDepthFromInteger(minz);
out.depthRangeMax = ToScaledDepthFromInteger(maxz);
bool scaleChanged = gstate_c.vpWidthScale != wScale || gstate_c.vpHeightScale != hScale;
bool offsetChanged = gstate_c.vpXOffset != xOffset || gstate_c.vpYOffset != yOffset;
@ -663,10 +685,6 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
}
}
float ToScaledDepth(u16 z) {
return z * (1.0f / 65535.0f);
}
static const BlendFactor genericALookup[11] = {
BlendFactor::DST_COLOR,
BlendFactor::ONE_MINUS_DST_COLOR,

View File

@ -205,6 +205,7 @@ static const CommandTableEntry commandTable[] = {
{GE_CMD_VIEWPORTXCENTER, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &DIRECTX9_GPU::Execute_ViewportType},
{GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &DIRECTX9_GPU::Execute_ViewportType},
{GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &DIRECTX9_GPU::Execute_ViewportType},
{GE_CMD_CLIPENABLE, FLAG_FLUSHBEFOREONCHANGE},
// Region
{GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &DIRECTX9_GPU::Execute_Region},
@ -288,7 +289,6 @@ static const CommandTableEntry commandTable[] = {
{GE_CMD_LSC3, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &DIRECTX9_GPU::Execute_Light3Param},
// Ignored commands
{GE_CMD_CLIPENABLE, 0},
{GE_CMD_TEXFLUSH, 0},
{GE_CMD_TEXLODSLOPE, 0},
{GE_CMD_TEXSYNC, 0},

View File

@ -481,11 +481,13 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) {
if (dirtyUniforms & DIRTY_DEPTHRANGE) {
// Depth is [0, 1] mapping to [minz, maxz], not too hard.
float minz = gstate.getDepthRangeMin();
float maxz = gstate.getDepthRangeMax();
float vpZScale = gstate.getViewportZScale();
float vpZCenter = gstate.getViewportZCenter();
float actualZRange = maxz - minz;
float viewZScale = actualZRange;
// These are just the reverse of the formulas in GPUStateUtils.
float halfActualZRange = vpZScale / gstate_c.vpDepthScale;
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
float viewZScale = halfActualZRange * 2.0f;
float viewZCenter = minz;
float viewZInvScale;

View File

@ -211,6 +211,7 @@ static const CommandTableEntry commandTable[] = {
{GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GLES_GPU::Execute_ViewportType},
{GE_CMD_VIEWPORTZSCALE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_DEPTHRANGE, &GLES_GPU::Execute_ViewportZType},
{GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_DEPTHRANGE, &GLES_GPU::Execute_ViewportZType},
{GE_CMD_CLIPENABLE, FLAG_FLUSHBEFOREONCHANGE},
// Region
{GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GLES_GPU::Execute_Region},
@ -294,7 +295,6 @@ static const CommandTableEntry commandTable[] = {
{GE_CMD_LSC3, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_LIGHT3, &GLES_GPU::Execute_Light3Param},
// Ignored commands
{GE_CMD_CLIPENABLE, 0},
{GE_CMD_TEXFLUSH, 0},
{GE_CMD_TEXLODSLOPE, 0},
{GE_CMD_TEXSYNC, 0},

View File

@ -589,11 +589,13 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
SetMatrix4x3(u_texmtx, gstate.tgenMatrix);
}
if ((dirty & DIRTY_DEPTHRANGE) && u_depthRange != -1) {
// Since depth is [-1, 1] mapping to [minz, maxz], this is easy.
float minz = gstate.getDepthRangeMin();
float maxz = gstate.getDepthRangeMax();
// Since depth is [-1, 1] mapping to [minz, maxz], this is easyish.
float vpZScale = gstate.getViewportZScale();
float vpZCenter = gstate.getViewportZCenter();
float halfActualZRange = (maxz - minz) * (1.0f / 2.0f);
// These are just the reverse of the formulas in GPUStateUtils.
float halfActualZRange = vpZScale / gstate_c.vpDepthScale;
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
float viewZScale = halfActualZRange;
float viewZCenter = minz + halfActualZRange;
float viewZInvScale;

View File

@ -375,6 +375,7 @@ struct GPUgstate {
int getRegionY2() const { return (region2 >> 10) & 0x3FF; }
// Note that the X1/Y1/Z1 here does not mean the upper-left corner, but half the dimensions. X2/Y2/Z2 are the center.
bool isClippingEnabled() const { return clipEnable & 1; }
float getViewportXScale() const { return getFloat24(viewportxscale); }
float getViewportYScale() const { return getFloat24(viewportyscale); }
float getViewportZScale() const { return getFloat24(viewportzscale); }