From 79f8a35c33d66d70bdf7f4cef146f59dd5a05846 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 16 Oct 2023 22:38:44 +0200 Subject: [PATCH] port: implement fisheye --- port/fast3d/gfx_api.h | 2 +- port/fast3d/gfx_opengl.cpp | 4 ++-- port/fast3d/gfx_pc.cpp | 6 +++--- port/fast3d/gfx_rendering_api.h | 2 +- port/src/pdsched.c | 6 ++---- port/src/video.c | 3 ++- src/game/bondview.c | 36 +++++++++++++++++++++++++++++++++ src/game/chr.c | 2 +- src/include/gbiex.h | 5 +++-- 9 files changed, 51 insertions(+), 15 deletions(-) diff --git a/port/fast3d/gfx_api.h b/port/fast3d/gfx_api.h index 7ff16356e..17a1a1310 100644 --- a/port/fast3d/gfx_api.h +++ b/port/fast3d/gfx_api.h @@ -45,7 +45,7 @@ int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int aut void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height, int upscale, int autoresize); void gfx_set_framebuffer(int fb, float noise_scale) ; void gfx_reset_framebuffer(void); -void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top); +void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back); void gfx_get_pixel_depth_prepare(float x, float y); uint16_t gfx_get_pixel_depth(float x, float y); diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index c4e5cbf22..4aefc1354 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -1110,7 +1110,7 @@ void gfx_opengl_select_texture_fb(int fb_id) { glBindTexture(GL_TEXTURE_2D, framebuffers[fb_id].clrbuf); } -void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top) { +void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool use_back) { if (!gfx_framebuffers_enabled || fb_dst >= (int)framebuffers.size() || fb_src >= (int)framebuffers.size()) { return; } @@ -1147,7 +1147,7 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top) { if (fb_src == 0) { // flip the dst rect to mirror the image vertically std::swap(dstY0, dstY1); - glReadBuffer(GL_FRONT); + glReadBuffer(use_back ? GL_BACK : GL_FRONT); } else { glReadBuffer(GL_COLOR_ATTACHMENT0); } diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 39c4bd26e..70e467f1c 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -2634,7 +2634,7 @@ static void gfx_run_dl(Gfx* cmd) { } break; case G_COPYFB_EXT: - gfx_copy_framebuffer(C0(12, 12), C0(0, 12), C1(16, 16), C1(0, 16)); + gfx_copy_framebuffer(C0(11, 11), C0(0, 11), (int16_t)C1(16, 16), (int16_t)C1(0, 16), C0(22, 1)); break; case G_RDPSETOTHERMODE: gfx_dp_set_other_mode(C0(0, 24), cmd->words.w1); @@ -2882,7 +2882,7 @@ extern "C" void gfx_set_framebuffer(int fb, float noise_scale) { gfx_rapi->clear_framebuffer(); } -extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top) { +extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back) { if (fb_src == 0 && left > 0 && top > 0) { // upscale the position left = left * gfx_current_dimensions.width / gfx_current_native_viewport.width; @@ -2890,7 +2890,7 @@ extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top) // flip Y top = gfx_current_dimensions.height - top - 1; } - gfx_rapi->copy_framebuffer(fb_dst, fb_src, left, top); + gfx_rapi->copy_framebuffer(fb_dst, fb_src, left, top, (bool)use_back); } extern "C" void gfx_reset_framebuffer(void) { diff --git a/port/fast3d/gfx_rendering_api.h b/port/fast3d/gfx_rendering_api.h index 69c56fd7b..86c5f6852 100644 --- a/port/fast3d/gfx_rendering_api.h +++ b/port/fast3d/gfx_rendering_api.h @@ -44,7 +44,7 @@ struct GfxRenderingAPI { bool opengl_invert_y, bool render_target, bool has_depth_buffer, bool can_extract_depth); bool (*start_draw_to_framebuffer)(int fb_id, float noise_scale); - void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top); + void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top, bool use_back); void (*clear_framebuffer)(void); void (*resolve_msaa_color_buffer)(int fb_id_target, int fb_id_source); void* (*get_framebuffer_texture_id)(int fb_id); diff --git a/port/src/pdsched.c b/port/src/pdsched.c index e6f3bcf0d..bd51c13f4 100644 --- a/port/src/pdsched.c +++ b/port/src/pdsched.c @@ -178,6 +178,8 @@ void osCreateScheduler(OSSched *sc, OSThread *thread, u8 mode, u32 numFields) osViSetEvent(&sc->interruptQ, (OSMesg)VIDEO_MSG, numFields); schedInitCrashLastRendered(); + + g_PrevFrameFb = videoCreateFramebuffer(0, 0, false, true); } void osScAddClient(OSSched *sc, OSScClient *c, OSMesgQueue *msgQ, bool is30fps) @@ -383,10 +385,6 @@ void schedConsiderScreenshot(void) g_MenuData.screenshottimer = 0; } - if (g_PrevFrameFb < 0) { - g_PrevFrameFb = videoCreateFramebuffer(0, 0, false, true); - } - if (g_PrevFrameCapTimer == 0) { videoCopyFramebuffer(g_PrevFrameFb, 0, -1, -1); g_PrevFrameCapTimer = -1; diff --git a/port/src/video.c b/port/src/video.c index 4bca41389..7bc86c270 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -170,7 +170,8 @@ void videoResizeFramebuffer(s32 target, u32 w, u32 h, s32 upscale, s32 autoresiz void videoCopyFramebuffer(s32 dst, s32 src, s32 left, s32 top) { - gfx_copy_framebuffer(dst, src, left, top); + // assume immediate copies always read the front buffer + gfx_copy_framebuffer(dst, src, left, top, false); } void videoResetTextureCache(void) diff --git a/src/game/bondview.c b/src/game/bondview.c index 576b9e1b9..9f4691c34 100644 --- a/src/game/bondview.c +++ b/src/game/bondview.c @@ -563,6 +563,24 @@ f32 bview0f142d74(s32 arg0, f32 arg1, f32 arg2, f32 arg3) return result; } +#ifndef PLATFORM_N64 + +static inline Gfx *bviewDrawFisheyeLine(Gfx *gdl, s32 viewleft, s32 viewwidth, s32 y, f32 scale) +{ + const f32 orighalfw = viewwidth * 0.5f; + const f32 xcenter = viewleft + orighalfw; + const f32 halfw = orighalfw * scale; + const s32 left = xcenter - halfw; + const s32 right = xcenter + halfw; + gSPImageRectangleEXT(gdl++, + left << 2, y << 2, viewleft, y, + right << 2, (y + 1) << 2, viewleft + viewwidth, y + 1, + 0, videoGetNativeWidth(), videoGetNativeHeight()); + return gdl; +} + +#endif + /** * Draw the fisheye curved effect when using an eyespy. * @@ -677,6 +695,12 @@ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 sta gdl = bviewPrepareStaticRgba16(gdl, colour, alpha); +#ifndef PLATFORM_N64 + // make a copy of the current back buffer contents that we will be using as a texture + gDPCopyFramebufferEXT(gdl++, g_PrevFrameFb, 0, 0, 0, G_ON); + gDPSetFramebufferTextureEXT(gdl++, 0, 0, 0, g_PrevFrameFb); +#endif + if (starting) { for (i = viewtop; i < viewtop + viewheight; i++) { if (i % 2) { @@ -684,7 +708,11 @@ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 sta gDPSetEnvColorViaWord(gdl++, (colour & 0xffffff00) | (spec & 0xff)); tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * startupfrac; +#ifdef PLATFORM_N64 gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); +#else + gdl = bviewDrawFisheyeLine(gdl, viewleft, viewwidth, i, tmp); +#endif } } @@ -710,13 +738,21 @@ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 sta } tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * f22; +#ifdef PLATFORM_N64 gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); +#else + gdl = bviewDrawFisheyeLine(gdl, viewleft, viewwidth, i, tmp); +#endif if (hit == EYESPYHIT_DAMAGE) { gDPSetEnvColorViaWord(gdl++, 0xddaaaa99); tmp = bview0f142d74(s2, f26, halfheight, sqhalfheight) * 1.03f; +#ifdef PLATFORM_N64 gdl = bviewCopyPixels(gdl, fb, i, 5, i, tmp, viewleft, viewwidth); +#else + gdl = bviewDrawFisheyeLine(gdl, viewleft, viewwidth, i, tmp); +#endif } s2 += s3; diff --git a/src/game/chr.c b/src/game/chr.c index 63e5aa7dd..c037e9a3a 100644 --- a/src/game/chr.c +++ b/src/game/chr.c @@ -6426,7 +6426,7 @@ Gfx *chrRenderCloak(Gfx *gdl, struct prop *chrprop, struct prop *thisprop) gDPPipeSync(gdl++); gSPTextureRectangle(gdl++, 0, 0, 60, 60, G_TX_RENDERTILE, 0, 0, 4096, 1024); #else - gDPCopyFramebufferEXT(gdl++, var8009ccc0[index], 0, uls, ult); + gDPCopyFramebufferEXT(gdl++, var8009ccc0[index], 0, uls, ult, G_ON); gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, ((((lrs - uls + 1) * G_IM_SIZ_16b_BYTES)+7)>>3), 0, 0, 0, G_TX_NOMIRROR | G_TX_WRAP, 4, G_TX_NOLOD, diff --git a/src/include/gbiex.h b/src/include/gbiex.h index dd5814b3a..83575cdc6 100644 --- a/src/include/gbiex.h +++ b/src/include/gbiex.h @@ -213,12 +213,13 @@ #define gDPSetFramebufferTextureEXT(pkt, f, s, w, i) \ gSetImage(pkt, G_SETTIMG_FB_EXT, f, s, w, i) -#define gDPCopyFramebufferEXT(pkt, dst, src, uls, ult) \ +#define gDPCopyFramebufferEXT(pkt, dst, src, uls, ult, back) \ { \ Gfx *_g = (Gfx *)(pkt); \ \ _g->words.w0 = _SHIFTL(G_COPYFB_EXT, 24, 8) \ - | _SHIFTL(dst, 12, 12) | _SHIFTL(src, 0, 12); \ + | _SHIFTL(dst, 11, 11) | _SHIFTL(src, 0, 11) | \ + _SHIFTL(back, 22, 1); \ _g->words.w1 = _SHIFTL(uls, 16, 16) | _SHIFTL(ult, 0, 16); \ }