Repository navigation
feat(render): an optional Enhanced look preset beside the classic look - #716
Merged
4 commits merged intoOct 17, 2026
Merged
4 commits merged into
4 commits merged into
Conversation
This was referenced Oct 13, 2026
alandarev
marked this pull request as ready for review
October 13, 2026 09:04
Use three persistent fenced staging buffers and four device-owned bitmap samplers instead of per-image allocations. Preserve whole-image uploads and existing decoder limits, check submission failures, and keep borrowed sampler ownership explicit. Add decoded-loader, failure/cleanup, truncated OZT and non-presenting GPU regression coverage, including intermediate readbacks and opt-in Vulkan validation. Refs sven-n#620
Adds a second look the player can switch to, while the classic look stays the default and draws exactly as before. `[Render] Look=Classic|Enhanced` (the "Enhanced graphics" checkbox in the options window, `$look classic| enhanced` in the chat) switches five features and anti-aliasing on or off together: - texture filtering: coverage-preserving RGBA8 mip chains and anisotropic sampling for world textures (terrain, objects, models), built on load or on first use; the chains upload through the fixed staging slots of the bitmap owner, as many levels per slot as fit; - per-pixel model lighting and fog (skinned_lit, basic_textured_fog): wrapped diffuse, rim and per-item specular (`material.specular` in the item-model JSON), a highlight roll-off that keeps burnt-out tops shaded; - dynamic model lights: the lights the game already adds to the terrain (candles, fires, spells) also light characters and monsters, through a per-frame light history with fade, range and strength limits; - a per-map light mood: deeper shade, a sun direction and model brightness per map, scaled from the baked terrain light; - scene post-processing: a selective bloom (bright effects, not the UI) and per-map colour grading tables; - multisample anti-aliasing, with alpha-to-coverage for alpha-tested cutouts, at `[Render] Antialiasing` samples (default 4, `$msaa off|2|4|8`); Classic always renders one sample per pixel. Every value of the preset lives in two data files with per-map overrides (`Data/Render/Look.json`, `Data/Maps/LightMood.json`); without them the built-in values apply. Builds with the control socket or the editor tune any value live (`$look set <name> <value>`, `$look save`), switch one feature for the session (`$texfilter`, `$lighting`, `$dynlights`, `$lightmood`, `$post`) and the DevEditor gets a Look panel. The anisotropy level (`[Render] Anisotropy`) is a setting of its own. With RmlUi: the checkbox is a row on the options window's Video tab (both themes; styled for `legacy`). Multisampling covers the frame's main pass only; the passes that render into single-sample targets (offscreen captures, RmlUi render targets, the post-RmlUi pass, flushed command ranges) replay with single-sample twins of the multisampled pipelines, built and released with them. Models drawn into RmlUi render targets (item previews, the character-creation preview) keep Classic sampling. Shaders are regenerated for all three backends with the project's commands; Vulkan is tested, Metal and Direct3D 12 compile but have not been run.
The Enhanced preset's values, chosen by comparing candidates side by side in towns, dungeons and fights across the Season 6 maps: - `Data/Render/Look.json`: model lighting (diffuse, rim, specular, wrap, highlight roll-off), dynamic light gain, range and caps for effect lights, bloom and grading; Icarus keeps a weaker bloom for its clouds; - `Data/Maps/LightMood.json`: the default mood and per-map moods (sun, shade, brightness) so that dark maps stay readable; - `Data/Grading/World2.png`: Dungeon's colour grading table; - `material.specular` 0.6 on the metal armour sets of the Dark Knight, Magic Gladiator and Dark Lord (115 parts); cloth-heavy sets stay matte, since specular applies to the whole model. Tests pin the shipped values and the list of shiny armour parts.
`docs/enhanced-look.md` describes the two looks, the settings, which file holds each piece of the Enhanced preset (model lighting, dynamic lights, bloom and grading, light mood, specular armour), per-map overrides, and the developer commands that tune values live and save them. `light-mood.md` and `post-processing.md` go deeper into those two pieces; the options window page names the "Enhanced graphics" checkbox.
alandarev
force-pushed
the
feature/enhanced-look
branch
from
October 15, 2026 20:26
eb69b1c to
89d74ce
Compare
This was referenced Oct 16, 2026
This was referenced Oct 17, 2026
Collaborator
|
This PR is merged unchanged into the integration PR #764, together with #622 and #758, with the conflicts against main's renderer changes resolved there. When #764 merges with a merge commit, GitHub marks this PR as merged too. Please don't push to this branch until #764 merges. A new commit here would leave this PR open, and it would have to be merged into #764 again. The main changes to how this PR fits in (#764's description has the full list):
Classic is unchanged against main (same spot in Noria: same draws, 0.55 vs 0.54 ms replay). I tested Enhanced on Vulkan with 4× anti-aliasing, bloom and the upscaled pack. |
nitoygo
added a commit
that referenced
this pull request
Oct 17, 2026
Resolved against main's renderer and the upscaled textures (#718, #758): - Skinned draws: Enhanced lighting (its pipelines, alpha-to-coverage, the world sampler, eye position, specular and world-space rows) moved into RecordSkinnedDraw, the path of the GPU mesh cache; the per-draw vertex upload of #716's old path is gone. A skinned draw's colour is one per-instance value, so it gives the draw's alpha. - Frame replay: #716's passes (frame, post-processed frame, continued flush) keep main's replay profiler scope and main's editor pass after RmlUi; #716's editor marker inside the replay is dropped. - The GPU body-shadow pipelines join the single-sample twins, so shadows still draw outside the multisampled main pass; they take no coverage. - Upload: #716's mip levels and the row bands share one staging loop; a texture can also have the GPU build its chain. The uploader is back to four shared samplers. - Textures: upscaled art is always mipmapped and sampled through #716's anisotropic samplers, in both looks. Opaque images get GPU-built mips, images with alpha #716's coverage-preserving CPU chain, at load and on the switch to Enhanced. The pixels are released after the upload, so that switch reads the file again. - Shader checks: both sides' shaders in the validation lists; the raw bone buffer check covers the skinned vertex shaders only. - Docs: the upload staging note, and Anisotropy applies to every mipmapped texture.
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Enhanced, an optional look beside the classic one. Classic stays the
default and draws exactly as before; a player switches with the "Enhanced
graphics" checkbox on the options window's Video tab (
[Render] Look=Classic|Enhanced, or$look classic|enhancedin the chat). Closes #715.Enhanced is a preset: one switch for six pieces, each of which is tuned in
data or settings, not code:
[Render] Anisotropylighting.*inData/Render/Look.json;material.specularper item modeldynamic.*inData/Render/Look.jsonData/Maps/LightMood.jsonbloom.*,grading.*inData/Render/Look.json;Data/Grading/[Render] Antialiasing(samples, default 4;$msaa off|2|4|8)Every value can be set for the whole game or per map. Developer builds (control
socket or editor) change any value live and save it back (
$look set <name> <value>,$look save, a Look panel in the DevEditor), and switch one piece forthe session (
$texfilter,$lighting,$dynlights,$lightmood,$post), soa server or a player can build their own Enhanced without touching the code.
docs/enhanced-look.mdhas the full map. Classic never uses anti-aliasing,whatever
Antialiasingsays, so it stays the game's own look.Media (Classic left, Enhanced right; the game's default camera):
More stills and a 32 s clip that flips between the looks:
https://github.com/alandarev/mumain-sven/tree/media/enhanced-look
Depends on #622
The first commit is #622 (bounded bitmap upload staging and shared samplers),
rebased onto current
main(112cece, after #610); #622 is updated to thesame commit. The rebase adapts it to
OztFile(its own OZT header check isreplaced by
Ozt::ReadHeader) and toErrorDialog, and moves the editor'sload-world bookkeeping and #610's
LoadImageExclusive,padToPowerOfTwoandCreateBitmapStorageinto the loader file #622 introduced. The mip chains uploadthrough its fixed staging slots:
BitmapGpuResources::Uploadtakes the levelsbelow the image and stages as many consecutive levels per 4 MiB slot as fit, so a
full 1024×1024 chain takes two submissions and no slot grows. If #622 is merged
first this PR shrinks to its own three commits.
Commits
fix(render): bound bitmap upload staging and share samplers— fix(render): bound bitmap upload staging and share samplers #622.feat(render): an Enhanced look preset beside the classic look— the code:Render/Look/(profile, preset, live tuning),Render/Lighting/(dynamic lights,light history, light mood),
Render/PostProcessing/,Render/Textures/(mip chains, filtering), renderer and shader changes, the options checkbox
(a row on the RmlUi option window's Video tab, both themes), config keys,
tests. Shaders are regenerated for SPIR-V, MSL and DXIL with the
project's commands.
feat(render): the tuned values of the Enhanced look—Data/Render/Look.json,Data/Maps/LightMood.json,Data/Grading/World2.png,material.specularon themetal armour sets, and tests that pin them.
docs: …—docs/enhanced-look.md,light-mood.md,post-processing.md,options window.
203 files, +19.6k/−1.1k; without shader blobs and data +18.4k/−1.0k, of which a
large part is tests (28 test files).
Rebased onto #610 (RmlUi)
option window (Video tab); the native combo box and layout changes are gone.
single-sample targets (RmlUi render targets, the post-RmlUi pass, offscreen
captures); while anti-aliasing is on they replay through single-sample twins
of the multisampled pipelines, built and released with them (Classic builds
none). Models drawn into RmlUi render targets keep Classic texture sampling.
Try it
Testing
main(112cece) does not build on Linux (#730). The Linux runs belowtherefore add the Linux build fixes of #719 (fork branch
fix/linux-gcc-build9ecbf65) under this branch, test-only; they are not part of this PR.
cmake --build --preset linux-x64-release+ctest: each commit builds andpasses on its own: 621 / 814 / 817 / 817.
linux-x64-mueditorrelease build +ctest: 855/855, exceptbundled_font_role_tests, which does not link with the editor onmaineither (Build fails on main (112cece4d): macOS, Windows/Linux with the editor, Linux; CI has not run on main since August #730 §4).
main2e41b7c: Quality Gates and theWindows editor-OFF build with its tests pass (https://github.com/alandarev/mumain-sven/actions/runs/38795377375,
https://github.com/alandarev/mumain-sven/actions/runs/38795377425). The other jobs fail on
maintoo, with the same errors(Build fails on main (112cece4d): macOS, Windows/Linux with the editor, Linux; CI has not run on main since August #730): Linux
strncpy_s, macOSWSclient.cpp:10828narrowing, and onWindows with the editor
bundled_font_role_tests, which does not link(
MouseX/MouseYtwice and 40 unresolvedWinmain.cppsymbols onmain;this branch adds three more of the same kind:
MuSetAntialiasingActive,MuSetAntialiasingPreference,MuSetTextureFilteringEnabled).no findings, on every commit.
(
MU_RUN_GPU_UPLOAD_TESTS=1 MU_GPU_UPLOAD_VALIDATION=1): a 1024×1024 chain (11levels) through the fixed slots reads back exactly at every level.
main(both with fix(linux) build/portability crashes #719's fixes) wereeach run twice (main, branch, main, branch) with a fresh configuration on 14
spots across the maps. On the 10 spots with enough still content to score,
over the 8×8 windows that are static in all four runs, the SSIM between the
two builds is at or above the SSIM between two runs of the same build on
every spot; on 9 of them 96–100 % of those windows are bit-identical between
the builds (Devias moves too much between runs to compare windows exactly; two
runs of the same build differ there as much). Classic creates none of the
single-sample pipelines above.
(towns, dungeons, fights), measured before the rebase onto feat: rmlui UI system #610: characters
no shinier in 7 and at least as readable against the ground in 6. The
exceptions: in the fight next to a bonfire the fire brightens the characters
(top 5 % of their pixels 253 vs 250 of 255) and the ground around them; in
the tavern, anti-aliasing softens the silhouette edges slightly
(figure-to-ground 0.99 vs 1.01; 1.007 without it). Spells light nearby
characters at least as much as in Classic (brightness rise 14.8 vs 13.0).
(before the rebase): Classic median 2.49 ms (p95 3.45), Enhanced with 4x
anti-aliasing 2.79 ms (p95 4.21).
/code-reviewover the whole diff (49 passes)found 9 points; 3 fixed in this branch (a stale comment, a look profile
whose existence cannot be checked is now reported unreadable, a lingering
light that finds the light list full no longer evicts a stronger one), 6
were not defects.
Open points
the project's commands and pass the reflection checks, but have not been run.
a crowded fight some distant lights are dropped.
Written with AI assistance and tested by hand.
Checklist
docs/CODING_RULES.md.docs/build/README.md).