[ADD] - 3D Scenes for pre-render areas (#5804)
* Hard removal 2D ones for now * override some scene values for prerender tests (#46) * Adult Link Cloudy * Fix: Child Link Night ToT Exterior * Fix for real now * Tweak: Skybox castle courtyard * WIP - adjusting for patterns * Hooked all code, needs testing * Hookified * Clean up * Update Fog Control * clang * Fix skybox override to only affect 3D pre-rendered scenes Prevent the 3D scene renderer from overriding skyboxes on all scenes Previously, the function was applying skybox changes to every scene, overriding the intended skyboxes throughout the game (Example: Kokiri Forest with a blue sky instead of it's original "greyish" one) Now it only applies custom skybox settings to scenes in the skyboxControlList, preserving original skyboxes for other scenes * Remove commentary and forgot to add Zelda's courtyard skybox * Move code to shipInit. * Early return for VB_SHOULD. * clang * Fix missing ! * Feedback fixes. * clang * Fix CVAR * Modify Skybox for scenes with multiple viewpoints. * setting position change to blend in the "modder stuff can do" * Adressed review * tooltip space missing, oops * InitFunc --------- Co-authored-by: Archez <Archez@users.noreply.github.com> Co-authored-by: Caladius <clatini88@gmail.com>
This commit is contained in:
161
soh/soh/Enhancements/Graphics/Disable2DBackgrounds.cpp
Normal file
161
soh/soh/Enhancements/Graphics/Disable2DBackgrounds.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <libultraship/bridge.h>
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ShipInit.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern SaveContext gSaveContext;
|
||||
extern PlayState* gPlayState;
|
||||
#include "macros.h"
|
||||
#include "variables.h"
|
||||
}
|
||||
|
||||
#define CVAR_NAME CVAR_ENHANCEMENT("3DSceneRender")
|
||||
#define CVAR_VALUE CVarGetInteger(CVAR_NAME, 0)
|
||||
|
||||
std::vector<SceneID> fogControlList = {
|
||||
SCENE_MARKET_ENTRANCE_DAY,
|
||||
SCENE_MARKET_ENTRANCE_NIGHT,
|
||||
SCENE_MARKET_ENTRANCE_RUINS,
|
||||
SCENE_BACK_ALLEY_DAY,
|
||||
SCENE_BACK_ALLEY_NIGHT,
|
||||
SCENE_MARKET_DAY,
|
||||
SCENE_MARKET_NIGHT,
|
||||
SCENE_MARKET_RUINS,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS,
|
||||
SCENE_KNOW_IT_ALL_BROS_HOUSE,
|
||||
SCENE_TWINS_HOUSE,
|
||||
SCENE_MIDOS_HOUSE,
|
||||
SCENE_SARIAS_HOUSE,
|
||||
SCENE_BACK_ALLEY_HOUSE,
|
||||
SCENE_BAZAAR,
|
||||
SCENE_KOKIRI_SHOP,
|
||||
SCENE_GORON_SHOP,
|
||||
SCENE_ZORA_SHOP,
|
||||
SCENE_POTION_SHOP_KAKARIKO,
|
||||
SCENE_POTION_SHOP_MARKET,
|
||||
SCENE_BOMBCHU_SHOP,
|
||||
SCENE_HAPPY_MASK_SHOP,
|
||||
SCENE_LINKS_HOUSE,
|
||||
SCENE_DOG_LADY_HOUSE,
|
||||
SCENE_STABLE,
|
||||
SCENE_IMPAS_HOUSE,
|
||||
SCENE_CARPENTERS_TENT,
|
||||
SCENE_GRAVEKEEPERS_HUT,
|
||||
};
|
||||
|
||||
std::vector<SceneID> skyboxSceneControlList = {
|
||||
SCENE_MARKET_ENTRANCE_DAY,
|
||||
SCENE_MARKET_ENTRANCE_NIGHT,
|
||||
SCENE_MARKET_ENTRANCE_RUINS,
|
||||
SCENE_BACK_ALLEY_DAY,
|
||||
SCENE_BACK_ALLEY_NIGHT,
|
||||
SCENE_MARKET_DAY,
|
||||
SCENE_MARKET_NIGHT,
|
||||
SCENE_MARKET_RUINS,
|
||||
SCENE_CASTLE_COURTYARD_ZELDA,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT,
|
||||
SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS,
|
||||
SCENE_FOREST_TEMPLE,
|
||||
};
|
||||
|
||||
std::vector<SkyboxId> skyboxIdControlList = {
|
||||
SKYBOX_BAZAAR,
|
||||
SKYBOX_HOUSE_LINK,
|
||||
SKYBOX_MARKET_ADULT,
|
||||
SKYBOX_MARKET_CHILD_DAY,
|
||||
SKYBOX_MARKET_CHILD_NIGHT,
|
||||
SKYBOX_HAPPY_MASK_SHOP,
|
||||
SKYBOX_HOUSE_KNOW_IT_ALL_BROTHERS,
|
||||
SKYBOX_HOUSE_OF_TWINS,
|
||||
SKYBOX_STABLES,
|
||||
SKYBOX_HOUSE_KAKARIKO,
|
||||
SKYBOX_KOKIRI_SHOP,
|
||||
SKYBOX_GORON_SHOP,
|
||||
SKYBOX_ZORA_SHOP,
|
||||
SKYBOX_POTION_SHOP_KAKARIKO,
|
||||
SKYBOX_POTION_SHOP_MARKET,
|
||||
SKYBOX_HOUSE_RICHARD,
|
||||
SKYBOX_HOUSE_IMPA,
|
||||
SKYBOX_TENT,
|
||||
SKYBOX_HOUSE_MIDO,
|
||||
SKYBOX_HOUSE_SARIA,
|
||||
SKYBOX_HOUSE_ALLEY,
|
||||
};
|
||||
|
||||
void Register3DPreRenderedScenes() {
|
||||
COND_HOOK(AfterSceneCommands, CVAR_VALUE, [](int16_t sceneNum) {
|
||||
// Check if this scene is in the skyboxControlList
|
||||
bool shouldControlSkybox = false;
|
||||
for (const auto& scene : skyboxSceneControlList) {
|
||||
if (sceneNum == scene) {
|
||||
shouldControlSkybox = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldControlSkybox) {
|
||||
// Add a skybox on scenes from skyboxSceneControlList
|
||||
gPlayState->envCtx.skyboxDisabled = false;
|
||||
|
||||
// Replace skybox with normal sky
|
||||
gPlayState->skyboxId = SKYBOX_NORMAL_SKY;
|
||||
// Apply the always cloudy skybox as an adult for Temple of Time and the Market
|
||||
if (sceneNum == SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS || sceneNum == SCENE_MARKET_RUINS ||
|
||||
sceneNum == SCENE_MARKET_ENTRANCE_RUINS) {
|
||||
gWeatherMode = 3;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
COND_HOOK(OnPlayDrawBegin, CVAR_VALUE, []() {
|
||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& scene : fogControlList) {
|
||||
if (scene == gPlayState->sceneNum) {
|
||||
if ((HREG(80) != 10) || (HREG(82) != 0)) {
|
||||
// Furthest possible fog and zFar
|
||||
gPlayState->view.zFar = 12800;
|
||||
gPlayState->lightCtx.fogNear = 996; // Set to 1000 to complete disable fog entirely
|
||||
gPlayState->lightCtx.fogFar = 12800;
|
||||
// General gray fog color
|
||||
gPlayState->lightCtx.fogColor[0] = 100;
|
||||
gPlayState->lightCtx.fogColor[1] = 100;
|
||||
gPlayState->lightCtx.fogColor[2] = 100;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
REGISTER_VB_SHOULD(VB_DRAW_2D_BACKGROUND, {
|
||||
if (CVAR_VALUE) {
|
||||
*should = false;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
REGISTER_VB_SHOULD(VB_LOAD_SKYBOX, {
|
||||
if (!gPlayState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CVAR_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& skybox : skyboxIdControlList) {
|
||||
if (gPlayState->skyboxCtx.skyboxId == skybox) {
|
||||
gPlayState->skyboxCtx.unk_140 = 0;
|
||||
*should = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc PreRender3DInitFunc(Register3DPreRenderedScenes, { CVAR_NAME });
|
||||
@@ -42,6 +42,7 @@ DEFINE_HOOK(OnPlayerFirstPersonControl, (Player * player));
|
||||
DEFINE_HOOK(OnPlayerProcessStick, ());
|
||||
DEFINE_HOOK(OnPlayerShieldControl, (float_t * sp50, float_t* sp54));
|
||||
DEFINE_HOOK(OnPlayDestroy, ());
|
||||
DEFINE_HOOK(OnPlayDrawBegin, ());
|
||||
DEFINE_HOOK(OnPlayDrawEnd, ());
|
||||
DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list originalArgs));
|
||||
DEFINE_HOOK(OnSaveFile, (int32_t fileNum));
|
||||
|
||||
@@ -186,6 +186,10 @@ void GameInteractor_ExecuteOnPlayDestroy() {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDestroy>();
|
||||
}
|
||||
|
||||
void GameInteractor_ExecuteOnPlayDrawBegin() {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawBegin>();
|
||||
}
|
||||
|
||||
void GameInteractor_ExecuteOnPlayDrawEnd() {
|
||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDrawEnd>();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ void GameInteractor_ExecuteOnPlayerShieldControl(float_t* sp50, float_t* sp54);
|
||||
void GameInteractor_ExecuteOnPlayerProcessStick();
|
||||
void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price);
|
||||
void GameInteractor_ExecuteOnPlayDestroy();
|
||||
void GameInteractor_ExecuteOnPlayDrawBegin();
|
||||
void GameInteractor_ExecuteOnPlayDrawEnd();
|
||||
bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...);
|
||||
|
||||
|
||||
@@ -2257,6 +2257,20 @@ typedef enum {
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0)
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_DRAW_2D_BACKGROUND,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0)
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_LOAD_SKYBOX,
|
||||
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
@@ -2270,6 +2284,7 @@ typedef enum {
|
||||
// #### `args`
|
||||
// - `*Player`
|
||||
VB_SET_STATIC_FLOOR_TYPE,
|
||||
|
||||
} GIVanillaBehavior;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -555,12 +555,17 @@ void SohMenu::AddMenuEnhancements() {
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Disables Grottos rotating with the Camera. To be used in conjuction with mods that want to "
|
||||
"replace grottos with 3D objects."));
|
||||
AddWidget(path, "Disable 2D Pre-Rendered Scenes", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("3DSceneRender"))
|
||||
.RaceDisable(false)
|
||||
.Options(CheckboxOptions().Tooltip("Disables 2D pre-rendered backgrounds. Enable this when using a mod that "
|
||||
"implements 3D backdrops for these areas.\n"
|
||||
"Requires Scene Change to alter."));
|
||||
AddWidget(path, "Ingame Text Spacing: %d", WIDGET_CVAR_SLIDER_INT)
|
||||
.CVar(CVAR_ENHANCEMENT("TextSpacing"))
|
||||
.RaceDisable(false)
|
||||
.Options(IntSliderOptions().Min(4).Max(6).DefaultValue(6).Tooltip(
|
||||
"Space between text characters (useful for HD font textures)."));
|
||||
|
||||
AddWidget(path, "Models & Textures", WIDGET_SEPARATOR_TEXT);
|
||||
AddWidget(path, "Disable LOD", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("DisableLOD"))
|
||||
|
||||
@@ -79,6 +79,7 @@ void OTRPlay_InitScene(PlayState* play, s32 spawn) {
|
||||
YREG(15) = 0;
|
||||
gSaveContext.worldMapArea = 0;
|
||||
OTRScene_ExecuteCommands(play, (SOH::Scene*)play->sceneSegment);
|
||||
|
||||
GameInteractor_ExecuteAfterSceneCommands(play->sceneNum);
|
||||
Play_InitEnvironment(play, play->skyboxId);
|
||||
/* auto data = static_cast<LUS::Vertex*>(Ship::Context::GetInstance()
|
||||
|
||||
@@ -472,6 +472,10 @@ extern "C" s32 OTRfunc_800973FC(PlayState* play, RoomContext* roomCtx) {
|
||||
gSegments[3] = VIRTUAL_TO_PHYSICAL(roomCtx->unk_34);
|
||||
|
||||
OTRScene_ExecuteCommands(play, (SOH::Scene*)roomCtx->roomToLoad);
|
||||
if (!GameInteractor_Should(VB_DRAW_2D_BACKGROUND, true)) {
|
||||
play->envCtx.skyboxDisabled = false;
|
||||
}
|
||||
|
||||
Player_SetBootData(play, GET_PLAYER(play));
|
||||
Actor_SpawnTransitionActors(play, &play->actorCtx);
|
||||
|
||||
|
||||
@@ -1390,6 +1390,8 @@ void Play_Draw(PlayState* play) {
|
||||
Gfx_SetupFrame(gfxCtx, 0, 0, 0);
|
||||
|
||||
if ((HREG(80) != 10) || (HREG(82) != 0)) {
|
||||
GameInteractor_ExecuteOnPlayDrawBegin();
|
||||
|
||||
POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP);
|
||||
POLY_XLU_DISP = Play_SetFog(play, POLY_XLU_DISP);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "global.h"
|
||||
#include "vt.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -256,6 +257,9 @@ s32 swapAndConvertJPEG(void* data) {
|
||||
|
||||
void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode,
|
||||
u16 tlutCount, f32 offsetX, f32 offsetY) {
|
||||
if (!GameInteractor_Should(VB_DRAW_2D_BACKGROUND, true)) {
|
||||
return;
|
||||
}
|
||||
Gfx* gfx = *gfxP;
|
||||
uObjBg* bg;
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@
|
||||
#include "assets/textures/skyboxes/vr_holy1_static.h"
|
||||
#include "assets/textures/skyboxes/vr_holy1_pal_static.h"
|
||||
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
u32 D_8012AC90[4] = {
|
||||
0x00000000,
|
||||
0x00010000,
|
||||
@@ -449,17 +452,23 @@ void func_800AF178(SkyboxContext* skyboxCtx, s32 arg1) {
|
||||
|
||||
void LoadSkyboxTex(SkyboxContext* skyboxCtx, int segmentIndex, int imageIndex, char* tex, int width, int height,
|
||||
int offsetW, int offsetH) {
|
||||
skyboxCtx->textures[segmentIndex][imageIndex] = tex;
|
||||
if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) {
|
||||
skyboxCtx->textures[segmentIndex][imageIndex] = tex;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSkyboxTexAtOffset(SkyboxContext* skyboxCtx, int segmentIndex, int imageIndex, char* tex, int width, int height,
|
||||
int offset) {
|
||||
skyboxCtx->textures[segmentIndex][imageIndex] = tex;
|
||||
if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) {
|
||||
skyboxCtx->textures[segmentIndex][imageIndex] = tex;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadSkyboxPalette(SkyboxContext* skyboxCtx, int paletteIndex, char* palTex, int width, int height) {
|
||||
skyboxCtx->palettes[paletteIndex] = palTex;
|
||||
skyboxCtx->palette_size = width * height;
|
||||
if (GameInteractor_Should(VB_LOAD_SKYBOX, true)) {
|
||||
skyboxCtx->palettes[paletteIndex] = palTex;
|
||||
skyboxCtx->palette_size = width * height;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* sSBVRFine0Tex[] = { gSunriseSkybox1Tex, gSunriseSkybox2Tex, gSunriseSkybox3Tex, gSunriseSkybox4Tex,
|
||||
|
||||
Reference in New Issue
Block a user