From 0e931b0be031580237eb707ee8fed1e859b52ced Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 5 Aug 2023 01:12:47 +0200 Subject: [PATCH] port: add gSPPerspNormalize support this fixes the viewmodel --- port/fast3d/gfx_opengl.cpp | 5 +++++ port/fast3d/gfx_pc.cpp | 22 ++++++++++++++++++++++ port/fast3d/gfx_rendering_api.h | 1 + 3 files changed, 28 insertions(+) diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 170f6fc76..9653c2213 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -763,6 +763,10 @@ static void gfx_opengl_set_depth_test_and_mask(bool depth_test, bool z_upd) { } } +static void gfx_opengl_set_depth_range(float znear, float zfar) { + glDepthRange(znear, zfar); +} + static void gfx_opengl_set_zmode_decal(bool zmode_decal) { if (zmode_decal) { glPolygonOffset(-2, -2); @@ -1000,6 +1004,7 @@ struct GfxRenderingAPI gfx_opengl_api = { gfx_opengl_upload_texture, gfx_opengl_set_sampler_parameters, gfx_opengl_set_depth_test_and_mask, + gfx_opengl_set_depth_range, gfx_opengl_set_zmode_decal, gfx_opengl_set_viewport, gfx_opengl_set_scissor, diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 31c99ae71..a9ab5508b 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -123,6 +123,8 @@ static struct RSP { uint32_t extra_geometry_mode; + float depth_zfar; + struct { // U0.16 uint16_t s, t; @@ -192,6 +194,7 @@ static struct RDP { static struct RenderingState { uint8_t depth_test_and_mask; // 1: depth test, 2: depth mask + float depth_zfar; bool decal_mode; bool alpha_blend; struct XYWidthHeight viewport, scissor; @@ -1207,6 +1210,11 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo gfx_rapi->set_depth_test_and_mask(depth_test, depth_mask); rendering_state.depth_test_and_mask = depth_test_and_mask; } + if (rsp.depth_zfar != rendering_state.depth_zfar) { + gfx_flush(); + gfx_rapi->set_depth_range(0.0f, rsp.depth_zfar); + rendering_state.depth_zfar = rsp.depth_zfar; + } bool zmode_decal = (rdp.other_mode_l & ZMODE_DEC) == ZMODE_DEC; if (zmode_decal != rendering_state.decal_mode) { @@ -1706,6 +1714,18 @@ static void gfx_sp_moveword(uint8_t index, uint16_t offset, uintptr_t data) { case G_MW_SEGMENT: segmentPointers[(offset >> 2) & 0xff] = data; break; + case G_MW_PERSPNORM: + // the default z range is around [100, 10000] + // data is 2 / (znear + zfar) represented as a 0.16 fixed point + // => (znear + zfar) = (2 / (data / 65536)) = 131072 / data + constexpr float full_range_mul = 1.f / 11000.f; // that's around the biggest value I got when testing + if (data == 0) { + rsp.depth_zfar = 1.f; + } else { + // sometimes this will overshoot 1 but GL can handle that + rsp.depth_zfar =((131072.f * full_range_mul) / (float)data); + } + break; } } @@ -2515,6 +2535,8 @@ extern "C" void gfx_init(struct GfxWindowManagerAPI* wapi, struct GfxRenderingAP int max_tex_size = min(8192, gfx_rapi->get_max_texture_size()); tex_upload_buffer = (uint8_t*)malloc(max_tex_size * max_tex_size * 4); } + + rsp.depth_zfar = 1.0f; } extern "C" void gfx_destroy(void) { diff --git a/port/fast3d/gfx_rendering_api.h b/port/fast3d/gfx_rendering_api.h index d79238031..0ac07629c 100644 --- a/port/fast3d/gfx_rendering_api.h +++ b/port/fast3d/gfx_rendering_api.h @@ -28,6 +28,7 @@ struct GfxRenderingAPI { void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height); void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt); void (*set_depth_test_and_mask)(bool depth_test, bool z_upd); + void (*set_depth_range)(float znear, float zfar); void (*set_zmode_decal)(bool zmode_decal); void (*set_viewport)(int x, int y, int width, int height); void (*set_scissor)(int x, int y, int width, int height);