From f8f00e6d9baf08dda5ac2e0ab5ae8ff33fc3e97f Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sun, 2 Jun 2024 23:15:33 -0500 Subject: [PATCH] Add draw distance enhancements for actors and scene geometry (#539) --- mm/2s2h/BenGui/BenMenuBar.cpp | 31 +++++++++++++++++ mm/include/PR/gbi.h | 1 + mm/src/code/z_actor.c | 63 ++++++++++++++++++++++++++++++++--- mm/src/code/z_play.c | 10 ++++++ 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index 35d3f5778e..264f047449 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -532,6 +532,37 @@ void DrawEnhancementsMenu() { "minor visual glitches that were covered up by the black bars\nPlease disable this " "setting before reporting a bug" }); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255)); + ImGui::SeparatorText("Unstable"); + ImGui::PopStyleColor(); + UIWidgets::CVarCheckbox( + "Disable Scene Geometry Distance Check", "gEnhancements.Graphics.DisableSceneGeometryDistanceCheck", + { .tooltip = + "Disables the distance check for scene geometry, allowing it to be drawn no matter how far " + "away it is from the player. This may have unintended side effects." }); + // BENTODO: Not implemented yet + // UIWidgets::CVarCheckbox("Widescreen Actor Culling", + // "gEnhancements.Graphics.ActorCullingAccountsForWidescreen", + // { .tooltip = "Adjusts the culling planes to account for widescreen resolutions. " + // "This may have unintended side effects." }); + if (UIWidgets::CVarSliderInt( + "Increase Actor Draw Distance: %dx", "gEnhancements.Graphics.IncreaseActorDrawDistance", 1, 5, 1, + { .tooltip = + "Increase the range in which Actors are drawn. This may have unintended side effects." })) { + CVarSetInteger("gEnhancements.Graphics.IncreaseActorUpdateDistance", + MIN(CVarGetInteger("gEnhancements.Graphics.IncreaseActorDrawDistance", 1), + CVarGetInteger("gEnhancements.Graphics.IncreaseActorUpdateDistance", 1))); + } + if (UIWidgets::CVarSliderInt( + "Increase Actor Update Distance: %dx", "gEnhancements.Graphics.IncreaseActorUpdateDistance", 1, 5, + 1, + { .tooltip = + "Increase the range in which Actors are updated. This may have unintended side effects." })) { + CVarSetInteger("gEnhancements.Graphics.IncreaseActorDrawDistance", + MAX(CVarGetInteger("gEnhancements.Graphics.IncreaseActorDrawDistance", 1), + CVarGetInteger("gEnhancements.Graphics.IncreaseActorUpdateDistance", 1))); + } + ImGui::EndMenu(); } diff --git a/mm/include/PR/gbi.h b/mm/include/PR/gbi.h index 262ac95e88..7820e61971 100644 --- a/mm/include/PR/gbi.h +++ b/mm/include/PR/gbi.h @@ -391,6 +391,7 @@ * G_EXTRAGEOMETRY flags: set extra custom geometry modes */ #define G_EX_INVERT_CULLING 0x00000001 +#define G_EX_ALWAYS_EXECUTE_BRANCH 0x00000002 /* Need these defined for Sprite Microcode */ #ifdef _LANGUAGE_ASSEMBLY diff --git a/mm/src/code/z_actor.c b/mm/src/code/z_actor.c index 532bb599fa..2a967694b6 100644 --- a/mm/src/code/z_actor.c +++ b/mm/src/code/z_actor.c @@ -3070,6 +3070,45 @@ s32 func_800BA2FC(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projec return false; } +// #region 2S2H [Enhancements] Allows us to increase the draw and update distance independently, mostly a modified +// version of the function above +void Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, + bool* shouldUpdate) { + s32 updateMulti = CVarGetInteger("gEnhancements.Graphics.IncreaseActorUpdateDistance", 1); + s32 drawMulti = CVarGetInteger("gEnhancements.Graphics.IncreaseActorDrawDistance", 1); + bool updateCheck = + (-(actor->uncullZoneScale * updateMulti) < projectedPos->z) && + (projectedPos->z < ((actor->uncullZoneForward * updateMulti) + (actor->uncullZoneScale * updateMulti))); + bool drawCheck = + (-(actor->uncullZoneScale * drawMulti) < projectedPos->z) && + (projectedPos->z < ((actor->uncullZoneForward * drawMulti) + (actor->uncullZoneScale * drawMulti))); + + if (updateCheck || drawCheck) { + f32 phi_f12; + f32 phi_f2 = CLAMP_MIN(projectedW, 1.0f); + f32 phi_f14; + f32 phi_f16; + + if (play->view.fovy != 60.0f) { + phi_f12 = actor->uncullZoneScale * play->projectionMtxFDiagonal.x * 0.76980036f; // sqrt(16/27) + + phi_f14 = play->projectionMtxFDiagonal.y * 0.57735026f; // 1 / sqrt(3) + phi_f16 = actor->uncullZoneScale * phi_f14; + phi_f14 *= actor->uncullZoneDownward; + } else { + phi_f16 = phi_f12 = actor->uncullZoneScale; + phi_f14 = actor->uncullZoneDownward; + } + + if (((fabsf(projectedPos->x) - phi_f12) < phi_f2) && ((-phi_f2 < (projectedPos->y + phi_f14))) && + ((projectedPos->y - phi_f16) < phi_f2)) { + *shouldDraw = drawCheck; + *shouldUpdate = updateCheck; + } + } +} +// #endregion + void Actor_DrawAll(PlayState* play, ActorContext* actorCtx) { s32 pad[2]; Gfx* ref2; @@ -3105,14 +3144,30 @@ void Actor_DrawAll(PlayState* play, ActorContext* actorCtx) { Actor_UpdateFlaggedAudio(actor); } - if (func_800BA2D8(play, actor)) { - actor->flags |= ACTOR_FLAG_40; + // #region 2S2H + bool shipShouldDraw = false; + bool shipShouldUpdate = false; + if (CVarGetInteger("gEnhancements.Graphics.IncreaseActorDrawDistance", 1) > 1 || + CVarGetInteger("gEnhancements.Graphics.IncreaseActorUpdateDistance", 1) > 1) { + Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw, + &shipShouldUpdate); + + if (shipShouldUpdate) { + actor->flags |= ACTOR_FLAG_40; + } else { + actor->flags &= ~ACTOR_FLAG_40; + } } else { - actor->flags &= ~ACTOR_FLAG_40; + if (func_800BA2D8(play, actor)) { + actor->flags |= ACTOR_FLAG_40; + } else { + actor->flags &= ~ACTOR_FLAG_40; + } } actor->isDrawn = false; - if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & actorFlags)) { + if ((actor->init == NULL) && (actor->draw != NULL) && ((actor->flags & actorFlags) || shipShouldDraw)) { + // #endregion if ((actor->flags & ACTOR_FLAG_REACT_TO_LENS) && ((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) || (play->actorCtx.lensMaskSize == LENS_MASK_ACTIVE_SIZE) || diff --git a/mm/src/code/z_play.c b/mm/src/code/z_play.c index a939ed2173..a4fd7e5b53 100644 --- a/mm/src/code/z_play.c +++ b/mm/src/code/z_play.c @@ -1373,11 +1373,21 @@ void Play_DrawMain(PlayState* this) { if (1) { u32 roomDrawFlags = ((1) ? 1 : 0) | (((void)0, 1) ? 2 : 0); // FAKE: + if (CVarGetInteger("gEnhancements.Graphics.DisableSceneGeometryDistanceCheck", 0)) { + gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_ALWAYS_EXECUTE_BRANCH); + gSPSetExtraGeometryMode(POLY_XLU_DISP++, G_EX_ALWAYS_EXECUTE_BRANCH); + } + Scene_Draw(this); if (this->roomCtx.unk78) { Room_Draw(this, &this->roomCtx.curRoom, roomDrawFlags & 3); Room_Draw(this, &this->roomCtx.prevRoom, roomDrawFlags & 3); } + + if (CVarGetInteger("gEnhancements.Graphics.DisableSceneGeometryDistanceCheck", 0)) { + gSPClearExtraGeometryMode(POLY_OPA_DISP++, G_EX_ALWAYS_EXECUTE_BRANCH); + gSPClearExtraGeometryMode(POLY_XLU_DISP++, G_EX_ALWAYS_EXECUTE_BRANCH); + } } if (this->skyboxCtx.skyboxShouldDraw) {