Skip to content

Models' level of detail can be chosen by the display's resolution - #344

Open
startupfoundry wants to merge 2 commits into
OpenCommunityEdition:mainfrom
startupfoundry:model-detail
Open

startupfoundry wants to merge 2 commits into
OpenCommunityEdition:mainfrom
startupfoundry:model-detail

Conversation

@startupfoundry

@startupfoundry startupfoundry commented Oct 13, 2026 •

Copy link
Copy Markdown

Halo chooses each model's level of detail (up to five) from its size in pixels, but it measures that size on the Xbox's 480-line screen, whatever the resolution. projection_world_to_screen.j is computed from the viewport's height, which is always 480 lines (render.c); d3d8_gl.c scales the real target afterwards. So at 1440p a model looks three times larger than the level was chosen for, and distant characters, vehicles and weapons drop to their simpler levels long before it would show. Neither window size nor supersampling changes the measure. The same b30 view at 854x480 and at 2400x1315 measured every model the same.

Screenshots: a10's cryo bay at 1080p, the same frame with each setting. The Chief in his pod is about 130 pixels tall. Stock draws him at a simpler level than the screen has room for; highest draws his most detailed level (the chest plate, shoulders, knee armour and helmet). Zoomed 7x, nearest-neighbour:
the Chief at stock (above) and highest (below), zoomed 7x

Switching between the two:
the Chief flipping between stock and highest

Where that is in the frame (native changes him only slightly at 1080p; it does more at higher resolutions):
a10 cryo bay at 1080p, with the zoomed area marked

Change: display.model_detail (HALO_MODEL_DETAIL), with a MODEL DETAIL row on Video Setup's Graphics screen:

  • "stock" (the default): as on the Xbox. The size is multiplied by exactly 1, so nothing changes.
  • "native": sizes are measured in the display's lines (without supersampling's factor, and never below 1x), so more detail is kept at a distance at high resolutions. Small far models the Xbox left out are drawn.
  • "highest": the models "native" draws, each at its most detailed level.

Details:

  • source/models/models.c (marked port:): the draw cutoff and the level loop multiply the size by halo_model_detail_scale() (d3d8_gl.c).
  • The first-person weapon and the sky pass 0 pixels and are unchanged in every mode.
  • The setting is read again when settings change, so the menu's OK applies at once.
  • On Android, which draws 480 lines, "native" is "stock"; "highest" still applies.
  • Models whose map has one level (b30's trees and rocks) don't change.
  • Network games: the level chosen is used only to draw. render_model is called from the objects' drawing (and their shadows), the first-person weapon and the sky. Nothing writes it back, and nothing the simulation, AI, collision or the host reads depends on it, so players with different settings can't diverge.

Test:

  • At 1080p, in a frozen b30 frame, I logged each model's size and level (temporary logging):
    • "stock": a grunt's corpse measures 20 px and is drawn at level 0 of 4.
    • "native": it measures 2.25 times as much and moves up a level, and assault rifles and plasma pistols move up one or two.
    • "highest": every model drawn is at level 4.
  • tools/harness passes, as does tools/test_web_build.py's test that the menus match their generator.
  • The Graphics screen was opened with debug.menu_open and shows the row.
  • Not checked with ssaa2x or on a 4K display, and not built for Android or the web here.

The game chooses a model's level of detail by its size in pixels on the
Xbox's 480 lines, whatever the resolution, so at high resolutions distant
models drop to their simpler levels long before it would show.
display.model_detail (HALO_MODEL_DETAIL): "stock" (the default) chooses as
the Xbox did; "native" by the size on the display's lines (without
supersampling's factor); "highest" draws the models native does, each at its
most detailed level. The first-person weapon and the sky are unchanged.
Android draws 480 lines, so there native is stock.

Checked: the same b30 view at 854x480 and 2400x1315 gave the same sizes in
stock; at 1080p native measures 2.25 times as much and moves the corpses and
weapons up a level, highest puts everything drawn at its top level. The
level chosen is used only to draw (render_model's callers are the objects',
the first-person weapon's and the sky's drawing), so nothing a network game
agrees on changes; stock multiplies by exactly 1. Not checked with ssaa2x or
on a 4K display, nor built for Android or the web.
Video Setup's Graphics screen gets a MODEL DETAIL row, which sets
display.model_detail. Its values are stock, native and highest. Its XML
is written by tools/port_settings.py's settings_files(), as
tools/ce_menus.py writes it; no other screen changes.

Checked: tools/test_web_build.py's test that the menus match their
generator; the screen opened with debug.menu_open shows the row with the
setting's value, above the help.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant