diff --git a/src/Camera.c b/src/Camera.c index ea832607c..8381b598d 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 48074e880..6c3b0ff0b 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,10 @@ static void Game_RenderFrame(double delta) { Gfx_Clear(); Camera.CurrentPos = Camera.Active->GetPosition(t); UpdateViewMatrix(); + Gfx_LoadMatrix(MATRIX_PROJECTION, &Gfx.Projection); - Gfx_LoadMatrix(MATRIX_VIEW, &Gfx.View); + + 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..3d89a0e99 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(); } @@ -911,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; } @@ -966,7 +972,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 +1057,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 +1814,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 +1989,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/Vectors.c b/src/Vectors.c index 74a1f66f7..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; @@ -182,21 +183,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; } @@ -276,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); } 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);