D3D9: Don't reduce zNear at default 70 FOV, reduces z-fighting with far away stuff

This commit is contained in:
UnknownShadow200 2020-12-05 23:48:25 +11:00
parent 9535e8866d
commit 98c8d459e4
6 changed files with 26 additions and 27 deletions

View file

@ -27,7 +27,7 @@ static void Camera_OnRawMovement(float deltaX, float deltaY) {
static void PerspectiveCamera_GetProjection(struct Matrix* proj) {
float fovy = Game_Fov * MATH_DEG2RAD;
float aspectRatio = (float)Game.Width / (float)Game.Height;
Gfx_CalcPerspectiveMatrix(fovy, aspectRatio, Gfx.MinZNear, (float)Game_ViewDistance, proj);
Gfx_CalcPerspectiveMatrix(fovy, aspectRatio, (float)Game_ViewDistance, proj);
}
static void PerspectiveCamera_GetView(struct Matrix* mat) {

View file

@ -29,6 +29,8 @@ static const int strideSizes[2] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTUR
static int curStride, curFormat = -1;
/* Whether mipmaps must be created for all dimensions down to 1x1 or not */
static cc_bool customMipmapsLevels;
#define ORTHO_NEAR -10000.0f
#define ORTHO_FAR 10000.0f
static cc_bool gfx_vsync, gfx_fogEnabled;
static float gfx_minFrameMs;
@ -312,6 +314,7 @@ static IDirect3D9* d3d;
static IDirect3DDevice9* device;
static DWORD createFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
static D3DFORMAT viewFormat, depthFormat;
static int depthBits;
static float totalMem;
static void D3D9_RestoreRenderStates(void);
@ -438,8 +441,7 @@ void Gfx_Create(void) {
CreateD3D9();
FindCompatibleViewFormat();
FindCompatibleDepthFormat();
/* With reversed z depth, near Z plane can be much closer with sufficient depth buffer precision */
Gfx.MinZNear = D3D9_DepthBufferBits() < 24 ? 0.05f : 0.001953125f;
depthBits = D3D9_DepthBufferBits();
customMipmapsLevels = true;
Gfx.ManagedTextures = true;
@ -915,16 +917,19 @@ void Gfx_LoadIdentityMatrix(MatrixType type) {
IDirect3DDevice9_SetTransform(device, matrix_modes[type], (const D3DMATRIX*)&Matrix_Identity);
}
#define d3d9_zN -10000.0f
#define d3d9_zF 10000.0f
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, d3d9_zN, d3d9_zF);
matrix->Row2.Z = 1.0f / (d3d9_zN - d3d9_zF);
matrix->Row3.Z = d3d9_zN / (d3d9_zN - d3d9_zF);
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, ORTHO_NEAR, ORTHO_FAR);
matrix->Row2.Z = 1.0f / (ORTHO_NEAR - ORTHO_FAR);
matrix->Row3.Z = ORTHO_NEAR / (ORTHO_NEAR - ORTHO_FAR);
}
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) {
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix) {
/* With reversed z depth, near Z plane can be much closer (with sufficient depth buffer precision) */
/* This reduces clipping with high FOV without sacrificing depth precision for faraway objects */
/* However for low FOV, don't reduce near Z in order to gain a bit more depth precision */
float zNear = (depthBits < 24 || fov <= 70) ? 0.05f : 0.001953125f;
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar);
/* Adjust the projection matrix to produce reversed Z values. */
/* Adjust the projection matrix to produce reversed Z values */
matrix->Row2.Z = -matrix->Row2.Z - 1.0f;
matrix->Row3.Z = -matrix->Row3.Z;
}
@ -1009,7 +1014,6 @@ static const char* D3D9_StrFlags(void) {
void Gfx_GetApiInfo(cc_string* info) {
D3DADAPTER_IDENTIFIER9 adapter = { 0 };
int pointerSize = sizeof(void*) * 8;
int depthBits = D3D9_DepthBufferBits();
float curMem;
IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &adapter);
@ -1108,7 +1112,6 @@ static GL_SetupVBRangeFunc gfx_setupVBRangeFunc;
static void GL_CheckSupport(void);
void Gfx_Create(void) {
GLContext_Create();
Gfx.MinZNear = 0.1f;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx.MaxTexWidth);
Gfx.MaxTexHeight = Gfx.MaxTexWidth;
Gfx.Created = true;
@ -1268,9 +1271,10 @@ void Gfx_SetDepthWrite(cc_bool enabled) { glDepthMask(enabled); }
void Gfx_SetDepthTest(cc_bool enabled) { gl_Toggle(GL_DEPTH_TEST); }
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, -10000.0f, 10000.0f);
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, ORTHO_NEAR, ORTHO_FAR);
}
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) {
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix) {
float zNear = 0.1f;
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar);
}

View file

@ -35,7 +35,7 @@ void Gfx_Free(void);
CC_VAR extern struct _GfxData {
/* Maximum dimensions textures can be created up to. (usually 1024 to 16384) */
int MaxTexWidth, MaxTexHeight;
float MinZNear;
float _unused;
/* Whether context graphics has been lost (all creation/render calls fail) */
cc_bool LostContext;
/* Whether some textures are created with mipmaps. */
@ -177,7 +177,7 @@ CC_API void Gfx_LoadIdentityMatrix(MatrixType type);
/* Calculates an orthographic matrix suitable with this backend. (usually for 2D) */
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix);
/* Calculates a projection matrix suitable with this backend. (usually for 3D) */
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix);
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix);
/* Outputs a .png screenshot of the backbuffer. */
cc_result Gfx_TakeScreenshot(struct Stream* output);

View file

@ -95,8 +95,7 @@ static void SetBaseOffset(void) {
static void OnProjectionChanged(void* obj) {
float fov = 70.0f * MATH_DEG2RAD;
float aspectRatio = (float)Game.Width / (float)Game.Height;
float zNear = Gfx.MinZNear;
Gfx_CalcPerspectiveMatrix(fov, aspectRatio, zNear, (float)Game_ViewDistance, &held_blockProjection);
Gfx_CalcPerspectiveMatrix(fov, aspectRatio, (float)Game_ViewDistance, &held_blockProjection);
}
/* Based off incredible gifs from (Thanks goodlyay!)

View file

@ -183,20 +183,17 @@ void Matrix_Orthographic(struct Matrix* result, float left, float right, float t
static double Tan_Simple(double x) { return Math_Sin(x) / Math_Cos(x); }
void Matrix_PerspectiveFieldOfView(struct Matrix* result, float fovy, float aspect, float zNear, float zFar) {
float c = zNear * (float)Tan_Simple(0.5f * fovy);
Matrix_PerspectiveOffCenter(result, -c * aspect, c * aspect, -c, c, zNear, zFar);
}
void Matrix_PerspectiveOffCenter(struct Matrix* result, float left, float right, float bottom, float top, float zNear, float zFar) {
/* Transposed, source https://msdn.microsoft.com/en-us/library/dd373537(v=vs.85).aspx */
/* For a FOV based perspective matrix, left/right/top/bottom are calculated as: */
/* left = -c * aspect, right = c * aspect, bottom = -c, top = c */
/* Calculations are simplified because of left/right and top/bottom symmetry */
*result = Matrix_Identity;
result->Row3.W = 0.0f;
result->Row0.X = (2.0f * zNear) / (right - left);
result->Row1.Y = (2.0f * zNear) / (top - bottom);
result->Row0.X = zNear / (c * aspect);
result->Row1.Y = zNear / c;
result->Row3.Z = -(2.0f * zFar * zNear) / (zFar - zNear);
result->Row2.X = (right + left) / (right - left);
result->Row2.Y = (top + bottom) / (top - bottom);
result->Row2.Z = -(zFar + zNear) / (zFar - zNear);
result->Row2.W = -1.0f;
}

View file

@ -123,7 +123,6 @@ CC_API void Matrix_Mul(struct Matrix* result, const struct Matrix* left, const s
void Matrix_Orthographic(struct Matrix* result, float left, float right, float top, float bottom, float zNear, float zFar);
void Matrix_PerspectiveFieldOfView(struct Matrix* result, float fovy, float aspect, float zNear, float zFar);
void Matrix_PerspectiveOffCenter(struct Matrix* result, float left, float right, float bottom, float top, float zNear, float zFar);
void Matrix_LookRot(struct Matrix* result, Vec3 pos, Vec2 rot);
cc_bool FrustumCulling_SphereInFrustum(float x, float y, float z, float radius);