From c2892d85077f88b14e941cdd6d7ec7928b49f2e0 Mon Sep 17 00:00:00 2001 From: Sauraen Date: Tue, 28 May 2024 05:33:44 -0700 Subject: [PATCH] Clean up F3DEX3 support (#118) * Basic cleanup * Added specular light sizes * Added camera world changes * Forgot specular size in the unused function --- include/config/config_graphics.h | 16 +++++----- include/config/config_safeguards.h | 16 ++-------- include/z64view.h | 3 ++ src/code/z_lights.c | 49 +++++++++++++++++++++--------- src/code/z_player_lib.c | 6 ++-- src/code/z_rcp.c | 2 +- src/code/z_room.c | 2 +- src/code/z_view.c | 42 +++++++++++++++++++++++++ 8 files changed, 95 insertions(+), 41 deletions(-) diff --git a/include/config/config_graphics.h b/include/config/config_graphics.h index 8dfb54218..85003889c 100644 --- a/include/config/config_graphics.h +++ b/include/config/config_graphics.h @@ -7,15 +7,17 @@ /** * F3DEX3 options - * This only works on "LLE-Emulators" like ares or ParaLLEl. It will not work on standard Project64. - * ``ENABLE_F3DEX3_RECOMMENDATIONS`` will enable the recommended changes listed in F3DEX3's readme - * ``ENABLE_F3DEX3_NEW_FEATURES`` will enable the required changes to use the new features from F3DEX3 + * This only works on real console or LLE emulators like ares or ParaLLEl. It + * will not work on legacy HLE emulators such as Project64. */ #define ENABLE_F3DEX3 true -#define ENABLE_F3DEX3_RECOMMENDATIONS true // missing matrix stuff + fast64 re-export process -#define ENABLE_F3DEX3_NOSYNCS false // not working properly currently -#define ENABLE_F3DEX3_LIGHT_RECO false // unfinished, faster but experimental (reco -> recommendations) -// #define ENABLE_F3DEX3_NEW_FEATURES true // not implemented yet +// Remove usually-unnecessary syncs from texture loading commands. Only matters +// for vanilla display lists--new ones exported from fast64 already have the +// syncs removed. This is buggy (graphical issues / crashes) as some vanilla DLs +// rely on the syncs within the texture loading commands for correctness. Some +// have already had the missing syncs manually added, but some have not been +// fixed yet. +#define ENABLE_F3DEX3_NOSYNCS false /** * Other graphical settings diff --git a/include/config/config_safeguards.h b/include/config/config_safeguards.h index 9c81ad26b..6604b5bbf 100644 --- a/include/config/config_safeguards.h +++ b/include/config/config_safeguards.h @@ -110,20 +110,8 @@ * config_game.h */ #if !ENABLE_F3DEX3 - #if ENABLE_F3DEX3_RECOMMENDATIONS - #undef ENABLE_F3DEX3_RECOMMENDATIONS - #define ENABLE_F3DEX3_RECOMMENDATIONS false - #endif - - #if ENABLE_F3DEX3_NEW_FEATURES - #undef ENABLE_F3DEX3_NEW_FEATURES - #define ENABLE_F3DEX3_NEW_FEATURES false - #endif - - #if ENABLE_F3DEX3_NOSYNCS - #undef ENABLE_F3DEX3_NOSYNCS - #define ENABLE_F3DEX3_NOSYNCS false - #endif + #undef ENABLE_F3DEX3_NOSYNCS + #define ENABLE_F3DEX3_NOSYNCS false #endif #if FORCE_WIDESCREEN diff --git a/include/z64view.h b/include/z64view.h index d506d5a36..058a4df04 100644 --- a/include/z64view.h +++ b/include/z64view.h @@ -28,6 +28,9 @@ typedef struct { /* 0x0A0 */ Mtx viewing; /* 0x0E0 */ Mtx* projectionPtr; /* 0x0E4 */ Mtx* viewingPtr; +#if ENABLE_F3DEX3 + PlainVtx* cameraWorldPosPtr; +#endif /* 0x0E8 */ Vec3f distortionOrientation; /* 0x0F4 */ Vec3f distortionScale; /* 0x100 */ f32 distortionSpeed; diff --git a/src/code/z_lights.c b/src/code/z_lights.c index 9e33032fc..541a56b42 100644 --- a/src/code/z_lights.c +++ b/src/code/z_lights.c @@ -61,16 +61,21 @@ void Lights_Draw(Lights* lights, GraphicsContext* gfxCtx) { OPEN_DISPS(gfxCtx, "../z_lights.c", 339); +#if ENABLE_F3DEX3 + // Copy ambient to light slot after last light + lights->l.l[lights->numLights].l.col[0] = lights->l.l[lights->numLights].l.colc[0] + = lights->l.a.l.col[0]; + lights->l.l[lights->numLights].l.col[1] = lights->l.l[lights->numLights].l.colc[1] + = lights->l.a.l.col[1]; + lights->l.l[lights->numLights].l.col[2] = lights->l.l[lights->numLights].l.colc[2] + = lights->l.a.l.col[2]; + + gSPSetLights(POLY_OPA_DISP++, lights->numLights, lights->l); + gSPSetLights(POLY_XLU_DISP++, lights->numLights, lights->l); +#else gSPNumLights(POLY_OPA_DISP++, lights->numLights); gSPNumLights(POLY_XLU_DISP++, lights->numLights); - -#if ENABLE_F3DEX3_LIGHT_RECO - gSPSetLights(POLY_OPA_DISP++, lights->numLights, *lights); - gSPSetLights(POLY_XLU_DISP++, lights->numLights, *lights); - - gSPAmbient(POLY_OPA_DISP++, &lights->l.a, lights->numLights); - gSPAmbient(POLY_XLU_DISP++, &lights->l.a, lights->numLights); -#else + light = &lights->l.l[0]; i = 0; @@ -80,16 +85,20 @@ void Lights_Draw(Lights* lights, GraphicsContext* gfxCtx) { } // ambient light is total number of lights + 1 - gSPAmbient(POLY_OPA_DISP++, &lights->l.a, ++i); - gSPAmbient(POLY_XLU_DISP++, &lights->l.a, i); + gSPLight(POLY_OPA_DISP++, &lights->l.a, ++i); + gSPLight(POLY_XLU_DISP++, &lights->l.a, i); #endif CLOSE_DISPS(gfxCtx, "../z_lights.c", 352); } Light* Lights_FindSlot(Lights* lights) { - u8 numLights = ENABLE_F3DEX3_RECOMMENDATIONS ? 9 : 7; - if (lights->numLights >= numLights) { +#if ENABLE_F3DEX3 +#define MAX_LIGHTS 9 +#else +#define MAX_LIGHTS 7 +#endif + if (lights->numLights >= MAX_LIGHTS) { return NULL; } else { return &lights->l.l[lights->numLights++]; @@ -120,7 +129,13 @@ void Lights_BindPoint(Lights* lights, LightParams* params, Vec3f* vec) { scale = posDiff / scale; scale = 1 - SQ(scale); #if ENABLE_F3DEX3 - light->l.type = 0; + light->l.type = 0; // directional + // Radius doesn't really mean the same thing as specular size; + // specular size is about how large the actual light emitting + // object is, and for a point light it's just a point. Plus it + // should be dependent on how rough the specular object is. + const s16 radius = params->point.radius; + light->l.size = radius > 1000 ? 1 : radius > 500 ? 2 : radius > 250 ? 3 : 4; #endif light->l.col[0] = light->l.colc[0] = params->point.color[0] * scale; light->l.col[1] = light->l.colc[1] = params->point.color[1] * scale; @@ -141,7 +156,10 @@ void Lights_BindDirectional(Lights* lights, LightParams* params, Vec3f* vec) { if (light != NULL) { #if ENABLE_F3DEX3 - light->l.type = 0; + light->l.type = 0; // directional + // The engine doesn't have a parameter in LightDirectional which + // represents specular size, so just make something up generally. + light->l.size = 3; #endif light->l.col[0] = light->l.colc[0] = params->dir.color[0]; light->l.col[1] = light->l.colc[1] = params->dir.color[1]; @@ -301,7 +319,8 @@ Lights* Lights_NewAndDraw(GraphicsContext* gfxCtx, u8 ambientR, u8 ambientG, u8 for (i = 0; i < numLights; i++) { #if ENABLE_F3DEX3 - lights->l.l[i].l.type = 0; + lights->l.l[i].l.type = 0; // directional + lights->l.l[i].l.size = 3; // some arbitrary specular size #endif lights->l.l[i].l.col[0] = lights->l.l[i].l.colc[0] = r; lights->l.l[i].l.col[1] = lights->l.l[i].l.colc[1] = g; diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 2ca9e9302..27b5c5591 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -1820,9 +1820,9 @@ void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject, gSPLoadGeometryMode(POLY_OPA_DISP++, G_ZBUFFER | G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH); gDPSetScissor(POLY_OPA_DISP++, G_SC_NON_INTERLACE, 0, 0, width, height); - if (!ENABLE_F3DEX3_RECOMMENDATIONS) { - gSPClipRatio(POLY_OPA_DISP++, FRUSTRATIO_1); - } +#if !ENABLE_F3DEX3 + gSPClipRatio(POLY_OPA_DISP++, FRUSTRATIO_1); +#endif gDPSetColorImage(POLY_OPA_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, depthFrameBuffer); gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); diff --git a/src/code/z_rcp.c b/src/code/z_rcp.c index f50a22234..13e77edee 100644 --- a/src/code/z_rcp.c +++ b/src/code/z_rcp.c @@ -818,7 +818,7 @@ Gfx sFillSetupDL[] = { gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH), gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), gsDPSetBlendColor(0, 0, 0, 8), -#if !ENABLE_F3DEX3_RECOMMENDATIONS +#if !ENABLE_F3DEX3 gsSPClipRatio(FRUSTRATIO_2), #endif gsSPEndDisplayList(), diff --git a/src/code/z_room.c b/src/code/z_room.c index 6a6dae900..6c427bd73 100644 --- a/src/code/z_room.c +++ b/src/code/z_room.c @@ -14,7 +14,7 @@ Gfx D_801270B0[] = { G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2), gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH), gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), -#if !ENABLE_F3DEX3_RECOMMENDATIONS +#if !ENABLE_F3DEX3 gsSPClipRatio(FRUSTRATIO_1), #endif gsSPEndDisplayList(), diff --git a/src/code/z_view.c b/src/code/z_view.c index 92c5666c8..ce6dfa807 100644 --- a/src/code/z_view.c +++ b/src/code/z_view.c @@ -6,6 +6,19 @@ vu32 sLogOnNextViewInit = true; s32 View_ApplyPerspective(View*); s32 View_ApplyOrtho(View*); +#if ENABLE_F3DEX3 +void View_SetCameraWorld(PlainVtx* cameraWorldPos, View* view){ + cameraWorldPos->c.pos[0] = (s16)view->eye.x; + cameraWorldPos->c.pos[1] = (s16)view->eye.y; + cameraWorldPos->c.pos[2] = (s16)view->eye.z; +} +PlainVtx* View_CreateCameraWorld(View* view){ + PlainVtx* cameraWorldPos = Graph_Alloc(view->gfxCtx, sizeof(PlainVtx)); + View_SetCameraWorld(cameraWorldPos, view); + return cameraWorldPos; +} +#endif + void View_ViewportToVp(Vp* dest, Viewport* src) { s32 width = src->rightX - src->leftX; s32 height = src->bottomY - src->topY; @@ -369,6 +382,11 @@ s32 View_ApplyPerspective(View* view) { viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); LOG_UTILS_CHECK_NULL_POINTER("viewing", viewing, "../z_view.c", 667); view->viewingPtr = viewing; + +#if ENABLE_F3DEX3 + PlainVtx* cameraWorldPos = View_CreateCameraWorld(view); + view->cameraWorldPosPtr = cameraWorldPos; +#endif if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) { view->eye.x += 1.0f; @@ -400,6 +418,10 @@ s32 View_ApplyPerspective(View* view) { gSPMatrix(POLY_OPA_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); gSPMatrix(POLY_XLU_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); +#if ENABLE_F3DEX3 + gSPCameraWorld(POLY_OPA_DISP++, cameraWorldPos); + gSPCameraWorld(POLY_XLU_DISP++, cameraWorldPos); +#endif CLOSE_DISPS(gfxCtx, "../z_view.c", 711); @@ -537,6 +559,11 @@ s32 View_ApplyPerspectiveToOverlay(View* view) { viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); LOG_UTILS_CHECK_NULL_POINTER("viewing", viewing, "../z_view.c", 848); view->viewingPtr = viewing; + +#if ENABLE_F3DEX3 + PlainVtx* cameraWorldPos = View_CreateCameraWorld(view); + view->cameraWorldPosPtr = cameraWorldPos; +#endif // This check avoids a divide-by-zero in guLookAt if eye == at if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) { @@ -553,6 +580,9 @@ s32 View_ApplyPerspectiveToOverlay(View* view) { view->viewing = *viewing; gSPMatrix(OVERLAY_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); +#if ENABLE_F3DEX3 + gSPCameraWorld(OVERLAY_DISP++, cameraWorldPos); +#endif CLOSE_DISPS(gfxCtx, "../z_view.c", 871); @@ -570,6 +600,10 @@ s32 View_UpdateViewingMatrix(View* view) { guLookAt(view->viewingPtr, view->eye.x, view->eye.y, view->eye.z, view->at.x, view->at.y, view->at.z, view->up.x, view->up.y, view->up.z); +#if ENABLE_F3DEX3 + View_SetCameraWorld(view->cameraWorldPosPtr, view); +#endif + CLOSE_DISPS(view->gfxCtx, "../z_view.c", 886); return 1; @@ -637,6 +671,11 @@ s32 View_ApplyTo(View* view, s32 mask, Gfx** gfxP) { viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); LOG_UTILS_CHECK_NULL_POINTER("viewing", viewing, "../z_view.c", 948); view->viewingPtr = viewing; + +#if ENABLE_F3DEX3 + PlainVtx* cameraWorldPos = View_CreateCameraWorld(view); + view->cameraWorldPosPtr = cameraWorldPos; +#endif VIEW_ERROR_CHECK_EYE_POS(view->eye.x, view->eye.y, view->eye.z); @@ -646,6 +685,9 @@ s32 View_ApplyTo(View* view, s32 mask, Gfx** gfxP) { view->viewing = *viewing; gSPMatrix(gfx++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION); +#if ENABLE_F3DEX3 + gSPCameraWorld(gfx++, cameraWorldPos); +#endif } view->flags = 0;