Use shifted invZ for Z to keep precision

This commit is contained in:
Luke Benstead 2020-05-13 20:59:40 +01:00
parent 2b9d8520bc
commit aa7320ab63

View File

@ -939,12 +939,25 @@ GL_FORCE_INLINE void divide(SubmissionTarget* target) {
/* Perform perspective divide on each vertex */
Vertex* vertex = _glSubmissionTargetStart(target);
/* PVR expects with invW or invZ as the final depth coordinate,
* but there are issues with that. Using invW means that orthographic
* projections fail (because W is always 1). invZ fails when stuff is near
* the near plane (because it ends up <= 0) so what we do is take invZ
* and add the near-plane distance (plus an epsilon value) to take it above 0
* then invert that. */
Matrix4x4* proj = _glGetProjectionMatrix();
float m22 = (*proj)[10];
float m32 = (*proj)[14];
float zNear = MATH_Fast_Divide((2.0f * m32), (2.0f * m22 - 2.0f));
ITERATE(target->count) {
float f = MATH_Fast_Invert(vertex->w);
vertex->xyz[0] *= f;
vertex->xyz[1] *= f;
vertex->xyz[2] *= f;
vertex->xyz[2] = PVR_MAX_Z - ((vertex->xyz[2] + 1.0f) * 0.5f);
vertex->xyz[2] = MATH_Fast_Invert(
vertex->xyz[2] + zNear + 0.05f
);
++vertex;
}
}