feat(graphics): view distance settings (foliage, LOD, grass, shadows) #2669

Open
github-sync wants to merge 2 commits from github/pr/2669 into main
Owner

@AnnoyedDev opened this pull request on GitHub · 2026-11-12 05:08 UTC · original

Players can't push view distances past the console's: foliage, detailed models, grass and shadows pop in close.

Tested on latest build of HookShot at this time, with an Ryzen 9 5950X, AMD 7900XTX, CachyOS

What changed

  • Graphics > Detail: Foliage distance (25–250%), Object detail (100–250%), Grass density (None, 25–300%), Shadow distance (25–400%), Contact shadows (On/Off), Base quality (Normal / Low = the game's handheld preset). Live, saved in hookshot_options.ini, English, French and Japanese translations.
  • Port of hotoni's Graphics-Menu (Lichii exlaunch mod), with credit: its per-frame hook at main+0x31d3200, rewritten in host C (host/oot_gfx.c) and installed with lifter.after (nx2/oot_gfx.py), build e0f3ccfa only. The mod's in-game menu hooks are not ported; the Insert menu holds the settings.
  • Every pointer link checks its vtable; scaled values keep the game's originals (no compounding, a value the game rewrites becomes the new original), and are restored at 100%. With every row at its default, the game is not touched.
  • Option IDs 52–57. Neither renderer interface changes, so no API version bump.

Tests

  • tests/test_oot_gfx.py: install gate, plus the host apply on a fake guest memory (no compounding, game writes, restore, vtable checks, no access at defaults).
  • tests/run_all.py: no new failures compared with main.

Screenshots

Menu: Graphics > Detail
menu

Comparaison

Hyrule Field

Lowest 100% (original) Maxed out
00 01 02
00 01 02
> [@AnnoyedDev](https://github.com/AnnoyedDev) opened this pull request on GitHub · 2026-11-12 05:08 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2669) Players can't push view distances past the console's: foliage, detailed models, grass and shadows pop in close. Tested on latest build of HookShot at this time, with an Ryzen 9 5950X, AMD 7900XTX, CachyOS ## What changed - Graphics > Detail: **Foliage distance** (25–250%), **Object detail** (100–250%), **Grass density** (None, 25–300%), **Shadow distance** (25–400%), **Contact shadows** (On/Off), **Base quality** (Normal / Low = the game's handheld preset). Live, saved in `hookshot_options.ini`, English, French and Japanese translations. - Port of hotoni's Graphics-Menu (Lichii exlaunch mod), with credit: its per-frame hook at `main+0x31d3200`, rewritten in host C (`host/oot_gfx.c`) and installed with `lifter.after` (`nx2/oot_gfx.py`), build `e0f3ccfa` only. The mod's in-game menu hooks are not ported; the Insert menu holds the settings. - Every pointer link checks its vtable; scaled values keep the game's originals (no compounding, a value the game rewrites becomes the new original), and are restored at 100%. With every row at its default, the game is not touched. - Option IDs 52–57. Neither renderer interface changes, so no API version bump. ## Tests - `tests/test_oot_gfx.py`: install gate, plus the host apply on a fake guest memory (no compounding, game writes, restore, vtable checks, no access at defaults). - `tests/run_all.py`: no new failures compared with `main`. ## Screenshots **Menu**: Graphics > Detail <img width="3840" height="2160" alt="menu" src="https://github.com/user-attachments/assets/5d9af773-939a-4bcf-98e1-f9b69f234374" /> **Comparaison** Hyrule Field | Lowest | 100% (original) | Maxed out | |---|---|---| | <img width="3834" height="2160" alt="00" src="https://github.com/user-attachments/assets/e37739d4-9af8-474e-bf1a-83d1c4b2a865" /> | <img width="3840" height="2160" alt="01" src="https://github.com/user-attachments/assets/46588599-7ed3-45ad-9a7b-74dd18088573" /> | <img width="3840" height="2160" alt="02" src="https://github.com/user-attachments/assets/81901c97-91e6-43ff-8915-05bae03a85a9" /> | | <img width="3837" height="2160" alt="00" src="https://github.com/user-attachments/assets/3f9bc0b0-7ca3-48b9-a0fb-805d79d19072" /> | <img width="3840" height="2160" alt="01" src="https://github.com/user-attachments/assets/144962be-26a2-4201-9493-5131f70162f6" /> | <img width="3840" height="2160" alt="02" src="https://github.com/user-attachments/assets/2bd32375-b70a-4319-9c96-da4a5f3650e6" /> | <!-- github-sync:item:2669 -->
Author
Owner

@AnnoyedDev commented on GitHub · 2026-11-12 05:51 UTC · original

Please note, the "original" mod/patch for the switch version have foliage and object density to a maximum of 400%, however, i found some bugs when taking some screenshot for comparison and there was some quirks. so i capped it at 250% where i found no bugs or quirks anywhere i tested.

> [@AnnoyedDev](https://github.com/AnnoyedDev) commented on GitHub · 2026-11-12 05:51 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2669#issuecomment-6815874285) Please note, the "original" mod/patch for the switch version have foliage and object density to a maximum of 400%, however, i found some bugs when taking some screenshot for comparison and there was some quirks. so i capped it at 250% where i found no bugs or quirks anywhere i tested. <!-- github-sync:c:6815874285 -->
Author
Owner

@Joey-Magnus reviewed on GitHub · 2026-11-12 14:33 UTC · original

I merged this into current main and ran the full tests/run_all.py: 427 passed, with only test_lift_cache failing, as it does on main here. So test_oot_gfx is in and nothing else breaks. Option IDs 52-57 are free on main, and leaving MKWVK_API_VERSION alone is right, since only enums were added.

Things I'd want settled before merging:

  • This ports hotoni's Graphics-Menu hook. Whether that's OK to carry (license or permission) and whether we want six new Graphics rows is a maintainer call.
  • The PR says scaled values keep the game's originals and are restored at 100%. That holds for the scale_floats paths, but not for LOD and character shadows. Once any row has moved (active never goes back to 0, host/oot_gfx.c:61-62), line 80 writes the constants O, 0.8·O and O to the LOD object every frame, and line 84 writes 30·S and 25·S to the character-shadow object. If the game uses other values for a scene or for its handheld preset (which "Base quality: Low" turns on), those get overwritten even at 100%. Capturing them with scale_floats like the others would fix it.
  • Only French and Japanese got the new texts. The other 11 menu languages will show English.
> [@Joey-Magnus](https://github.com/Joey-Magnus) reviewed on GitHub · 2026-11-12 14:33 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2669#pullrequestreview-5876228616) I merged this into current main and ran the full tests/run_all.py: 427 passed, with only test_lift_cache failing, as it does on main here. So test_oot_gfx is in and nothing else breaks. Option IDs 52-57 are free on main, and leaving `MKWVK_API_VERSION` alone is right, since only enums were added. Things I'd want settled before merging: - This ports hotoni's Graphics-Menu hook. Whether that's OK to carry (license or permission) and whether we want six new Graphics rows is a maintainer call. - The PR says scaled values keep the game's originals and are restored at 100%. That holds for the `scale_floats` paths, but not for LOD and character shadows. Once any row has moved (`active` never goes back to 0, host/oot_gfx.c:61-62), line 80 writes the constants O, 0.8·O and O to the LOD object every frame, and line 84 writes 30·S and 25·S to the character-shadow object. If the game uses other values for a scene or for its handheld preset (which "Base quality: Low" turns on), those get overwritten even at 100%. Capturing them with `scale_floats` like the others would fix it. - Only French and Japanese got the new texts. The other 11 menu languages will show English. <!-- github-sync:r:5876228616 -->
Author
Owner

@Ekibunnel commented on GitHub · 2026-11-12 15:50 UTC · original

Nice PR, I did build and test this a bit.
Foliage distance, Grass density, Shadow distance, work as expected.

But there is an issue with Object detail :

Some higher quality object LOD do scale on camera distances to do progressive and seamless transition.
And it is an issue when said higher LOD are loaded from farther away than the base game.
They become invisible because they do not take the new render distance into account.

100% (original) Maxed out
100% (original)https://youtu.be/GmAl4qqXvjA Maxed outhttps://youtu.be/5RbJxjmsgxM

Either those objects should be excluded or the way they check for camera distance should be edited to take the new render distance into account.

> [@Ekibunnel](https://github.com/Ekibunnel) commented on GitHub · 2026-11-12 15:50 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2669#issuecomment-6828441040) Nice PR, I did build and test this a bit. Foliage distance, Grass density, Shadow distance, work as expected. But there is an issue with Object detail : Some higher quality object LOD do scale on camera distances to do progressive and seamless transition. And it is an issue when said higher LOD are loaded from farther away than the base game. They become invisible because they do not take the new render distance into account. 100% (original) | Maxed out -- | -- <img width="1920" height="1080" alt="100% (original)" src="https://github.com/user-attachments/assets/d35ef44b-e196-464f-aca3-8c1be897846e" />https://youtu.be/GmAl4qqXvjA | <img width="1920" height="1080" alt="Maxed out" src="https://github.com/user-attachments/assets/027be0e7-f269-43ab-afe6-90cc25df5b53" />https://youtu.be/5RbJxjmsgxM Either those objects should be excluded or the way they check for camera distance should be edited to take the new render distance into account. <!-- github-sync:c:6828441040 -->
Author
Owner

@AnnoyedDev commented on GitHub · 2026-11-12 17:19 UTC · original

Nice PR, I did build and test this a bit.

Foliage distance, Grass density, Shadow distance, work as expected.

But there is an issue with Object detail :

Some higher quality object LOD do scale on camera distances to do progressive and seamless transition.

And it is an issue when said higher LOD are loaded from farther away than the base game.

They become invisible because they do not take the new render distance into account.

100% (original) | Maxed out

-- | --

100% (original)https://youtu.be/GmAl4qqXvjA | Maxed outhttps://youtu.be/5RbJxjmsgxM

Either those objects should be excluded or the way they check for camera distance should be edited to take the new render distance into account.

Thanks a lot. I will take a look once I'm at home to try to address this issue. If no resolution is made on my hand I think we can simply remove object detail quality setting and keep the rest. I totally forgot to check with free camera

> [@AnnoyedDev](https://github.com/AnnoyedDev) commented on GitHub · 2026-11-12 17:19 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2669#issuecomment-6830726066) > Nice PR, I did build and test this a bit. > > Foliage distance, Grass density, Shadow distance, work as expected. > > > > But there is an issue with Object detail : > > > > Some higher quality object LOD do scale on camera distances to do progressive and seamless transition. > > And it is an issue when said higher LOD are loaded from farther away than the base game. > > They become invisible because they do not take the new render distance into account. > > > > 100% (original) | Maxed out > > -- | -- > > <img width="1920" height="1080" alt="100% (original)" src="https://github.com/user-attachments/assets/d35ef44b-e196-464f-aca3-8c1be897846e" />https://youtu.be/GmAl4qqXvjA | <img width="1920" height="1080" alt="Maxed out" src="https://github.com/user-attachments/assets/027be0e7-f269-43ab-afe6-90cc25df5b53" />https://youtu.be/5RbJxjmsgxM > > > > Either those objects should be excluded or the way they check for camera distance should be edited to take the new render distance into account. Thanks a lot. I will take a look once I'm at home to try to address this issue. If no resolution is made on my hand I think we can simply remove object detail quality setting and keep the rest. I totally forgot to check with free camera <!-- github-sync:c:6830726066 -->
Commenting is not possible because the repository is archived.
No description provided.