From 8e9c084dd2241ade86817ec97f601b369e4c127c Mon Sep 17 00:00:00 2001 From: Cheesse Date: Thu, 5 Nov 2020 15:42:27 -0500 Subject: [PATCH 1/3] Use reversed z depth for D3D backend Removes depth artifacts at high view distances for 24 bit depth buffers. Allows the decrease of the near Z plane in those circumstances. --- src/Game.c | 8 ++++++-- src/Graphics.c | 25 ++++++++++++++++++------- src/Graphics.h | 3 +++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Game.c b/src/Game.c index 5d50010bf..146abc463 100644 --- a/src/Game.c +++ b/src/Game.c @@ -65,7 +65,7 @@ cc_string Game_Mppass = String_FromArray(mppassBuffer); const char* const FpsLimit_Names[FPS_LIMIT_COUNT] = { "LimitVSync", "Limit30FPS", "Limit60FPS", "Limit120FPS", "Limit144FPS", "LimitNone", -}; +}; static struct IGameComponent* comps_head; static struct IGameComponent* comps_tail; @@ -600,8 +600,12 @@ static void Game_RenderFrame(double delta) { Gfx_Clear(); Camera.CurrentPos = Camera.Active->GetPosition(t); UpdateViewMatrix(); + + Gfx_PrepProjection(&Gfx.Projection); Gfx_LoadMatrix(MATRIX_PROJECTION, &Gfx.Projection); - Gfx_LoadMatrix(MATRIX_VIEW, &Gfx.View); + Gfx_PrepProjection(&Gfx.Projection); + + Gfx_LoadMatrix(MATRIX_VIEW, &Gfx.View); if (!Gui_GetBlocksWorld()) { Game_Render3D(delta, t); diff --git a/src/Graphics.c b/src/Graphics.c index 48ae19bc7..873c06854 100644 --- a/src/Graphics.c +++ b/src/Graphics.c @@ -372,7 +372,11 @@ static void FindCompatibleDepthFormat(void) { for (i = 0; i < Array_Elems(formats); i++) { depthFormat = formats[i]; res = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, viewFormat, viewFormat, depthFormat); - if (!res) return; + if (!res) { + /* With reversed z depth, the near Z plane can be set much lower with more depth buffer bits. */ + Gfx.MinZNear = i > 3 ? 0.05f : 0.001953125f; + return; + } } Logger_Abort("Failed to create depth buffer. Graphics drivers may not be installed."); } @@ -427,7 +431,6 @@ void Gfx_Create(void) { FindCompatibleViewFormat(); FindCompatibleDepthFormat(); - Gfx.MinZNear = 0.05f; customMipmapsLevels = true; Gfx.ManagedTextures = true; Gfx.Created = true; @@ -477,7 +480,7 @@ static void Gfx_RestoreState(void) { IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 127); IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); - IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATEREQUAL); D3D9_RestoreRenderStates(); } @@ -883,6 +886,12 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { *#########################################################################################################################*/ static D3DTRANSFORMSTATETYPE matrix_modes[3] = { D3DTS_PROJECTION, D3DTS_VIEW, D3DTS_TEXTURE0 }; +void Gfx_PrepProjection(struct Matrix* matrix) { + /* Adjust the projection matrix to produce reversed Z values. */ + matrix->Row2.Z = -matrix->Row2.Z - 1; + matrix->Row3.Z = -matrix->Row3.Z; +} + void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) { if (type == MATRIX_TEXTURE) { matrix->Row2.X = matrix->Row3.X; /* NOTE: this hack fixes the texture movements. */ @@ -966,7 +975,7 @@ void Gfx_BeginFrame(void) { void Gfx_Clear(void) { DWORD flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER; - cc_result res = IDirect3DDevice9_Clear(device, 0, NULL, flags, gfx_clearCol, 1.0f, 0); + cc_result res = IDirect3DDevice9_Clear(device, 0, NULL, flags, gfx_clearCol, 0.0f, 0); if (res) Logger_Abort2(res, "D3D9_Clear"); } @@ -1051,10 +1060,10 @@ void Gfx_OnWindowResize(void) { Gfx_LoseContext(" (resizing window)"); } #define _GL_DYNAMIC_DRAW 0x88E8 #define _GL_TEXTURE_MAX_LEVEL 0x813D -#define _GL_FRAGMENT_SHADER 0x8B30 +#define _GL_FRAGMENT_SHADER 0x8B30 #define _GL_VERTEX_SHADER 0x8B31 -#define _GL_COMPILE_STATUS 0x8B81 -#define _GL_LINK_STATUS 0x8B82 +#define _GL_COMPILE_STATUS 0x8B81 +#define _GL_LINK_STATUS 0x8B82 #define _GL_INFO_LOG_LENGTH 0x8B84 #if defined CC_BUILD_GL11 @@ -1808,6 +1817,7 @@ void Gfx_SetFogMode(FogFunc func) { void Gfx_SetTexturing(cc_bool enabled) { } void Gfx_SetAlphaTest(cc_bool enabled) { gfx_alphaTest = enabled; SwitchProgram(); } +void Gfx_PrepProjection(struct Matrix* matrix) { } void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) { if (type == MATRIX_VIEW || type == MATRIX_PROJECTION) { if (type == MATRIX_VIEW) _view = *matrix; @@ -1982,6 +1992,7 @@ void Gfx_SetAlphaTest(cc_bool enabled) { gl_Toggle(GL_ALPHA_TEST); } static GLenum matrix_modes[3] = { GL_PROJECTION, GL_MODELVIEW, GL_TEXTURE }; static int lastMatrix; +void Gfx_PrepProjection(struct Matrix* matrix) { } void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) { if (type != lastMatrix) { lastMatrix = type; glMatrixMode(matrix_modes[type]); } glLoadMatrixf((float*)matrix); diff --git a/src/Graphics.h b/src/Graphics.h index a864eb9ef..0d5cbb790 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -170,6 +170,9 @@ CC_API void Gfx_DrawVb_IndexedTris(int verticesCount); /* Special case Gfx_DrawVb_IndexedTris_Range for map renderer */ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex); +/* Prepares the given matrix to be loaded as a projection matrix. */ +/* Must be called before and after loading a perspective projection matrix. */ +CC_API void Gfx_PrepProjection(struct Matrix* matrix); /* Loads the given matrix over the currently active matrix. */ CC_API void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix); /* Loads the identity matrix over the currently active matrix. */ From 7798881442808b37d0c811db73bd6630de1e941e Mon Sep 17 00:00:00 2001 From: Cheesse Date: Fri, 6 Nov 2020 21:09:28 -0500 Subject: [PATCH 2/3] Modify perspective matrix when calculating instead Also simplify calculation of perspective matrix and remove pointless operations. --- src/Camera.c | 2 +- src/Game.c | 2 -- src/Graphics.c | 9 +++------ src/Graphics.h | 3 --- src/Vectors.c | 15 +++++---------- src/Vectors.h | 1 - 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/Camera.c b/src/Camera.c index 20c31458e..efbb044fb 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -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; - Matrix_PerspectiveFieldOfView(proj, fovy, aspectRatio, Gfx.MinZNear, (float)Game_ViewDistance); + Gfx_CalcPerspectiveMatrix(fovy, aspectRatio, Gfx.MinZNear, (float)Game_ViewDistance, proj); } static void PerspectiveCamera_GetView(struct Matrix* mat) { diff --git a/src/Game.c b/src/Game.c index 146abc463..0ec3f3fb6 100644 --- a/src/Game.c +++ b/src/Game.c @@ -601,9 +601,7 @@ static void Game_RenderFrame(double delta) { Camera.CurrentPos = Camera.Active->GetPosition(t); UpdateViewMatrix(); - Gfx_PrepProjection(&Gfx.Projection); Gfx_LoadMatrix(MATRIX_PROJECTION, &Gfx.Projection); - Gfx_PrepProjection(&Gfx.Projection); Gfx_LoadMatrix(MATRIX_VIEW, &Gfx.View); diff --git a/src/Graphics.c b/src/Graphics.c index 873c06854..3d89a0e99 100644 --- a/src/Graphics.c +++ b/src/Graphics.c @@ -886,12 +886,6 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { *#########################################################################################################################*/ static D3DTRANSFORMSTATETYPE matrix_modes[3] = { D3DTS_PROJECTION, D3DTS_VIEW, D3DTS_TEXTURE0 }; -void Gfx_PrepProjection(struct Matrix* matrix) { - /* Adjust the projection matrix to produce reversed Z values. */ - matrix->Row2.Z = -matrix->Row2.Z - 1; - matrix->Row3.Z = -matrix->Row3.Z; -} - void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix) { if (type == MATRIX_TEXTURE) { matrix->Row2.X = matrix->Row3.X; /* NOTE: this hack fixes the texture movements. */ @@ -920,6 +914,9 @@ void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) { } void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, struct Matrix* matrix) { Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar); + /* Adjust the projection matrix to produce reversed Z values. */ + matrix->Row2.Z = -matrix->Row2.Z - 1.0f; + matrix->Row3.Z = -matrix->Row3.Z; } diff --git a/src/Graphics.h b/src/Graphics.h index 0d5cbb790..a864eb9ef 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -170,9 +170,6 @@ CC_API void Gfx_DrawVb_IndexedTris(int verticesCount); /* Special case Gfx_DrawVb_IndexedTris_Range for map renderer */ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex); -/* Prepares the given matrix to be loaded as a projection matrix. */ -/* Must be called before and after loading a perspective projection matrix. */ -CC_API void Gfx_PrepProjection(struct Matrix* matrix); /* Loads the given matrix over the currently active matrix. */ CC_API void Gfx_LoadMatrix(MatrixType type, struct Matrix* matrix); /* Loads the identity matrix over the currently active matrix. */ diff --git a/src/Vectors.c b/src/Vectors.c index 74a1f66f7..a5355605c 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -182,21 +182,16 @@ 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); -} + float zDelta = 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 */ *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->Row3.Z = -(2.0f * zFar * zNear) / (zFar - zNear); + result->Row0.X = zNear / (c * aspect); + result->Row1.Y = zNear / c; + result->Row3.Z = (2.0f * zFar * zNear) / zDelta; - result->Row2.X = (right + left) / (right - left); - result->Row2.Y = (top + bottom) / (top - bottom); - result->Row2.Z = -(zFar + zNear) / (zFar - zNear); + result->Row2.Z = (zFar + zNear) / zDelta; result->Row2.W = -1.0f; } diff --git a/src/Vectors.h b/src/Vectors.h index 8f6f50b17..00cb09866 100644 --- a/src/Vectors.h +++ b/src/Vectors.h @@ -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); From e83d66a7a654bd28b811e91a9fbc1b700a29b882 Mon Sep 17 00:00:00 2001 From: Cheesse Date: Thu, 3 Dec 2020 17:23:01 -0500 Subject: [PATCH 3/3] Change frustum culling calculation for D3D --- src/Vectors.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Vectors.c b/src/Vectors.c index a5355605c..9961412e6 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -2,6 +2,7 @@ #include "ExtMath.h" #include "Funcs.h" #include "Constants.h" +#include "Core.h" void Vec3_Lerp(Vec3* result, const Vec3* a, const Vec3* b, float blend) { result->X = blend * (b->X - a->X) + a->X; @@ -271,10 +272,19 @@ void FrustumCulling_CalcFrustumEquations(struct Matrix* projection, struct Matri frustum33 = clip[15] - clip[13]; FrustumCulling_Normalise(&frustum30, &frustum31, &frustum32, &frustum33); - /* Extract the FAR plane */ + /* Extract the FAR plane (Different for each graphics backend) */ +#if defined(CC_BUILD_GL) frustum40 = clip[3] - clip[2]; frustum41 = clip[7] - clip[6]; frustum42 = clip[11] - clip[10]; frustum43 = clip[15] - clip[14]; +#elif defined(CC_BUILD_D3D9) + frustum40 = clip[2]; + frustum41 = clip[6]; + frustum42 = clip[10]; + frustum43 = clip[14]; +#else +#error "Vectors.c: No graphics backend chosen." +#endif FrustumCulling_Normalise(&frustum40, &frustum41, &frustum42, &frustum43); }