938 lines
55 KiB
Markdown
938 lines
55 KiB
Markdown
# Campaign AR — Atmospheric Rendering / Shader Packs
|
||
|
||
**Date:** 2026-08-21
|
||
**Status:** MACHINE-LOCAL STAGE 2 COMPLETE — the authored sun-and-moon
|
||
shadow-source extension, Stage 1 owner gate, connected ACE matrix, dense A/B,
|
||
long lifetime, graphical package lifecycle, shader, locked-restore, Release,
|
||
and complete-test gates pass. A second-client remote-player row, unavailable
|
||
physical GPU classes, and final project-owner pack-off/pack-on acceptance remain
|
||
external closeout gates; the campaign is not yet declared shipped.
|
||
**Phase id:** **Campaign AR** — assigned by the project owner on 2026-08-22
|
||
**Scheduling:** originally held for the post-M7 rendering-polish pass; the
|
||
project owner explicitly authorized implementation on 2026-08-21. This
|
||
owner-directed campaign is now Campaign AR and does not displace the active M4
|
||
gameplay work. The previously referenced #268 + TS-8 stat-chain package is
|
||
already complete and retired, so it is no longer a scheduling dependency.
|
||
|
||
## Goal
|
||
|
||
Add an opt-in enhanced-graphics system whose headline feature is **real-time
|
||
directional shadows cast by trees, monsters, players, and buildings as
|
||
Dereth's authored sun and moons move across the sky**. The same system can add
|
||
bloom, filmic tonemapping, colour grading, vignette, sun rays, and later
|
||
volumetric shafts, with useful quality levels on weak through high-end
|
||
hardware. Sun rays and volumetric shafts remain sun-only effects; the approved
|
||
moon scope applies to Tier 2 directional shadows.
|
||
|
||
Campaign AR executes in two stages. Stage 1 fixed the dense-scene transform
|
||
ceiling and shadow quality, completed authored sun/dominant-moon/secondary-moon
|
||
source selection, and finished every automated gate that did not require the
|
||
project owner's physical-display judgment. The owner accepted the subsequent
|
||
live visual/performance round on 2026-08-22 after the default Atmospheric
|
||
exposure was corrected from 1.0 to 0.80. The machine-local Stage 2 rows are now
|
||
complete. Remaining closeout is limited to a second connected remote player,
|
||
unavailable physical-hardware rows, and final owner acceptance; it does not add
|
||
another renderer feature tier.
|
||
|
||
Stage 1's dense-scene regression is pinned by the connected failures already
|
||
captured on 2026-08-22: Atmospheric fell back at 68,395, 67,581, and even
|
||
65,538 combined world matrices against the old 65,536-matrix binding ceiling.
|
||
The corrected connected launch must exceed that historical workload without
|
||
persisting acdream-default fallback or splitting the authoritative pose data.
|
||
|
||
The enhancement is a shader pack, not a rewrite of acdream's renderer or AC's
|
||
art. **acdream's current retail-faithful renderer** remains the default,
|
||
authoritative path. References below to the “default” or “retail-faithful” path
|
||
always mean acdream—not the original retail executable.
|
||
|
||
The evidence and constraints for this design are recorded in the
|
||
[terrain and atmospheric rendering findings](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md),
|
||
especially [the measured renderer baseline](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md#5-renderer-state-relevant-to-atmospheric-work)
|
||
and [the requested tier model](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md#6-wanted-work--atmospheric-rendering-user-stated).
|
||
The approved celestial identity, priority, transform, and direction-versus-
|
||
energy contract are pinned by the
|
||
[Dereth celestial shadow-source research](../research/2026-08-22-dereth-celestial-shadow-sources.md).
|
||
|
||
## Opt-in contract
|
||
|
||
1. **acdream's current renderer is the default.** With no pack selected, the current render graph,
|
||
shaders, render targets, submissions, lighting, colours, and screenshots
|
||
remain authoritative. No enhancement resource or pass is created.
|
||
2. **Selection is explicit.** Installing a pack does not enable it. The user
|
||
selects one pack and one quality preset in Display settings. `acdream
|
||
default (retail-faithful)` is always present and cannot be removed.
|
||
3. **One pack owns the enhancement graph.** Packs do not stack. This prevents
|
||
ambiguous pass ordering, incompatible HDR conventions, and unbounded GPU
|
||
cost.
|
||
4. **The renderer owns the RHI.** A pack declares assets, semantic pass hooks,
|
||
capabilities, resources, and quality variants. It never receives Vulkan
|
||
handles or mutates the authoritative scene, streaming, gameplay, or
|
||
physics owners.
|
||
5. **Failure returns to acdream's default renderer.** Unsupported capabilities,
|
||
malformed assets, shader/pipeline candidate-creation failure, or an invalid
|
||
pass graph disables the complete pack and restores acdream's default path
|
||
with a visible reason. A half-enabled pack is never rendered. A terminal
|
||
`VK_ERROR_DEVICE_LOST` cannot render either path on the lost device; it tears
|
||
down that renderer/device lifetime, and retail remains authoritative while a
|
||
fresh renderer/device is constructed and the pack is validated again.
|
||
6. **Divergence is honest.** Enhanced screenshots are intentionally not retail
|
||
parity evidence. The default path remains the comparison oracle and the
|
||
enhancement choice is recorded in diagnostics and screenshot metadata.
|
||
7. **No scheduling claim.** Rendering phases stay frozen until the M7 polish
|
||
pass unless the project owner explicitly reprioritizes this work.
|
||
|
||
## Capability tiers
|
||
|
||
The costs below are **planning estimates**, not measurements. They are
|
||
incremental GPU p50 targets for a representative discrete GPU at 1920x1080;
|
||
every slice must replace them with physical-hardware measurements. Tier-1
|
||
pixel effects scale with output resolution, so 4K has roughly four times the
|
||
1080p fragment workload. Shadow-map cost depends more on caster count, map
|
||
resolution, and cascade count than on output resolution.
|
||
|
||
| Tier | Contents | Prerequisite | Rough incremental GPU cost at 1080p |
|
||
|---|---|---|---:|
|
||
| acdream default | Current authoritative retail-faithful rendering | Current mandatory Vulkan/RHI capabilities | 0 ms |
|
||
| 1 | Bloom, ACES filmic tonemap, colour grade, vignette | Main-world colour intermediate and fullscreen passes | 0.35–0.80 ms |
|
||
| 1 | Screen-space sun rays (crepuscular) | Authored sun screen position plus an occlusion mask; **no shadow maps** | 0.20–0.50 ms |
|
||
| 2 | **Moving authored sun-and-moon cascaded directional shadows from trees, monsters, players, and houses/buildings** | A second scene pass, selected-celestial view/projection matrices, sampled depth maps, caster pipeline variants | 1.50–3.00 ms |
|
||
| 2+ | Sun-only volumetric light shafts | Reuse Tier-2 shadow infrastructure only while the selected source is the authored sun, plus authored weather | 0.15–0.40 ms |
|
||
| Later | SSAO and water reflections | Scene depth plus normal inputs and separate designs | Not budgeted here |
|
||
| Out | True PBR | AC lacks authored per-texture normal/roughness/metalness maps | Not planned |
|
||
|
||
Tier numbers express prerequisites, not a forced bundle. A pack may offer
|
||
Tier 1 without shadows. Tier 2 always includes the complete shadow-caster
|
||
classes; weak-hardware presets reduce range, cascade count, and resolution
|
||
rather than silently dropping monsters, trees, or buildings.
|
||
|
||
## Tier 2 headline: Dereth's moving authored sun-and-moon shadows
|
||
|
||
The [measured renderer state](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md#5-renderer-state-relevant-to-atmospheric-work)
|
||
already supplies retail's single directional colour/energy channel from
|
||
`SkyStateProvider`. Tier 2 augments it with the visible authored celestial
|
||
positions documented in the
|
||
[Dereth celestial shadow-source research](../research/2026-08-22-dereth-celestial-shadow-sources.md).
|
||
The camera-relative cascaded map selects, in order, the visible above-horizon
|
||
sun (`0x01001348`), dominant haloed moon (`0x01001F6A`), or secondary moon
|
||
(`0x01001F67`). The selected mesh's exact rendered transform supplies shadow
|
||
direction; retail's one interpolated `DirColor * DirBright` channel supplies
|
||
colour/energy. Moon texture brightness and mesh luminosity never manufacture a
|
||
second world light. As those authored bodies move, tree branches, monsters,
|
||
players, houses, and other eligible world geometry cast correspondingly moving
|
||
shadows.
|
||
|
||
This source selection is an explicit opt-in pack enhancement. It is not a
|
||
claim that the retail executable rendered real-time moon shadows, and it does
|
||
not alter acdream's default retail-faithful scene lighting. Screen-space sun
|
||
rays and volumetric shafts continue to use only the authored sun; they do not
|
||
switch to either moon.
|
||
|
||
The required behavior is:
|
||
|
||
- Terrain and opaque world geometry receive shadows. Terrain, buildings,
|
||
statics, procedural scenery, the local player, remote players, and creatures
|
||
cast them when resident and visible to the main outdoor world.
|
||
- Foliage and other cutout materials use an alpha-sampling shadow fragment
|
||
shader. An empty depth fragment shader would turn each tree plane into a
|
||
solid rectangular shadow.
|
||
- Animated casters reuse the exact per-part transforms already published in
|
||
the N.5 SSBO. The shadow pass must not create a second animation pose or
|
||
gameplay entity projection.
|
||
- Cascades follow the camera and are texel-stabilized. Their reach is clamped
|
||
to the resident two-tier streaming window; the pack does not extend world
|
||
streaming or issue speculative loads.
|
||
- The celestial directional-shadow pass is outdoor-only. Dungeon and EnvCell lighting remains
|
||
authored per-cell lighting. Entering an interior retires or idles outdoor
|
||
shadow work without leaving stale maps on screen.
|
||
- Shadow direction follows the selected visible above-horizon sun, dominant
|
||
moon, or secondary moon. The authored directional colour/energy remains
|
||
`DirColor * DirBright`; active day/weather pack policy may soften or reduce
|
||
it without inventing a second celestial clock, light-energy channel, or
|
||
weather system. A time with no eligible above-horizon body has no
|
||
directional shadow; night is not itself a disable condition.
|
||
- Transparent blend materials do not cast an opaque silhouette by default.
|
||
Only existing opaque and cutout classifications participate until a
|
||
material-specific transparent-shadow contract is designed.
|
||
|
||
The pass reuses the retained resident scene. It must not run PView, portal
|
||
traversal, or per-object CPU visibility classification once per cascade.
|
||
Initially, each cascade draws the bounded resident caster set through the
|
||
existing batched/MDI ownership. If that is too expensive, the next permitted
|
||
step is GPU culling—not repeated CPU culling or per-object submissions.
|
||
|
||
## Pack API surface sketch
|
||
|
||
The public declarations belong in the BCL-only
|
||
`AcDream.Plugin.Abstractions` assembly. The graphical App supplies the
|
||
implementation and translates the declarations to the Vulkan RHI. Headless
|
||
hosts expose no render-pack registry and never load pack assets.
|
||
|
||
This is an API shape, not code committed by this design:
|
||
|
||
```csharp
|
||
public interface IRenderPackPlugin
|
||
{
|
||
void Register(IRenderPackRegistry registry);
|
||
}
|
||
|
||
public interface IRenderPackRegistry
|
||
{
|
||
IDisposable Register(RenderPackDescriptor descriptor, IRenderPackAssets assets);
|
||
}
|
||
|
||
public interface IRenderPackAssets
|
||
{
|
||
Stream OpenRead(string assetKey);
|
||
}
|
||
|
||
public sealed record RenderPackDescriptor(
|
||
string Id,
|
||
string DisplayName,
|
||
Version PackVersion,
|
||
int PackApiVersion,
|
||
RenderPackTier HighestTier,
|
||
IReadOnlyList<RenderCapability> RequiredCapabilities,
|
||
IReadOnlyList<RenderCapability> OptionalCapabilities,
|
||
IReadOnlyList<RenderResourceDeclaration> Resources,
|
||
IReadOnlyList<RenderPassDeclaration> Passes,
|
||
IReadOnlyList<SceneReplayDeclaration> SceneReplays,
|
||
IReadOnlyList<PipelineVariantDeclaration> PipelineVariants,
|
||
IReadOnlyList<RenderQualityPreset> QualityPresets,
|
||
IReadOnlyList<RenderSettingDeclaration> Settings,
|
||
AtmospherePolicyDeclaration? AtmospherePolicy);
|
||
```
|
||
|
||
A pack declares:
|
||
|
||
- a stable ID, display name, pack version, and pack-API version;
|
||
- its highest tier and a human-readable feature summary;
|
||
- mandatory and optional GPU capabilities and per-preset limits;
|
||
- shader assets and fixed renderer semantic inputs, including world colour,
|
||
scene depth, optional normals, selected celestial shadow direction/energy,
|
||
sun direction/screen position for sun-only effects, active weather, camera
|
||
matrices, shadow-caster transforms, and frame time;
|
||
- intermediate images/buffers by relative or absolute extent, format class,
|
||
usage, lifetime, and estimated bytes;
|
||
- passes at renderer-owned hooks such as `ShadowDepthBeforeWorld`,
|
||
`AtmosphereBeforeToneMap`, `ToneMap`, and
|
||
`AfterToneMapBeforePrivateViewports`;
|
||
- renderer-owned scene replays such as `OutdoorDirectionalShadowCasters`, with
|
||
requested cascade views and existing caster/material classes
|
||
(`Terrain`, `OpaqueWorld`, `AlphaCutoutWorld`, `AnimatedOpaque`, and
|
||
`AnimatedAlphaCutout`); the renderer resolves those classes from its
|
||
retained scene and records their existing batched draws;
|
||
- fixed pipeline variants for shadow-caster depth and main-world shadow
|
||
receivers. A variant names its base semantic (`Terrain`, `WorldMesh`, or
|
||
`EnvCell`), shader asset, compatible material classes, and declared inputs
|
||
such as cascade matrices, directional depth maps, and sampler state; it does
|
||
not replace visibility, batching, mesh ownership, or draw submission code;
|
||
- quality presets, user-visible settings with bounded ranges, and declared
|
||
incremental GPU/VRAM budgets; and
|
||
- an atmosphere policy: explicit directional-source/sun-elevation response
|
||
curves and a mapping from AC's categorical `activeDayGroup` values to effect
|
||
multipliers. These values live in the visible pack declaration, not as hidden
|
||
renderer constants; AC remains the owner of celestial position, directional
|
||
energy, and weather state.
|
||
|
||
The renderer—not the pack—defines descriptor layouts, validates SPIR-V and
|
||
resource declarations, resolves semantic scene-replay and pipeline-variant
|
||
requests, builds pipelines, schedules barriers, owns frame-flight and teardown,
|
||
and supplies immutable frame inputs. Packs cannot add arbitrary draw callbacks,
|
||
read gameplay owners, submit command buffers, retain borrowed frame views, or
|
||
address resources outside their registration. The built-in pack's Tier-2
|
||
caster pass and receiver shaders must be expressible entirely through these
|
||
same public declarations.
|
||
|
||
### Selection and fail-safe lifecycle
|
||
|
||
1. Discover manifests and descriptors without creating GPU objects.
|
||
2. Show compatibility and estimated cost in Display settings. Unsupported
|
||
packs remain visible with the exact missing capability; they cannot be
|
||
selected.
|
||
3. On explicit selection, validate the whole descriptor, all assets, resource
|
||
ceilings, hooks, and shader interfaces; then build a complete candidate
|
||
pipeline set off to the side.
|
||
4. Atomically activate the candidate only after every required object exists.
|
||
Until then acdream's default path continues rendering.
|
||
5. Persist `pack id + pack version + preset`, never a positional index. If the
|
||
pack disappears or becomes incompatible, select `acdream default` and
|
||
retain the failure notice.
|
||
6. On runtime validation or post-recreation candidate failure, withdraw all
|
||
pack passes/resources at a frame boundary and resume acdream's default
|
||
renderer. Do not repeatedly retry a failing pack during the session.
|
||
7. Unload and reconnect use the normal render-generation and GPU-flight
|
||
retirement rules. No pack object may retain a world generation, scene
|
||
entity, or collectible plugin load context.
|
||
|
||
In this campaign, **device recreation** means disposing the complete old
|
||
renderer, Vulkan context, and device, then constructing a fresh context/device,
|
||
re-probing capabilities, and validating selection again with retail active
|
||
until the candidate is complete. It does **not** mean live, in-process recovery
|
||
from `VK_ERROR_DEVICE_LOST`; device loss remains terminal to that renderer and
|
||
device lifetime.
|
||
|
||
The built-in Atmospheric Rendering pack should be the first consumer of this
|
||
same API. It must not receive private renderer shortcuts that third-party packs
|
||
cannot express.
|
||
|
||
The public v1 authoring surface, manifest schema, shader semantic bindings,
|
||
failure guidance, validator command, and external no-op sample are indexed by
|
||
the [render-pack SDK](../render-packs/README.md).
|
||
|
||
## Frame-graph placement
|
||
|
||
With the pack off, the frozen retail graph is unchanged. With a pack selected,
|
||
the renderer builds a separate enhancement graph:
|
||
|
||
1. Update the existing immutable world frame, including authored sky objects,
|
||
the retail directional colour/energy channel, and weather.
|
||
2. Outdoors, select the visible above-horizon sun/dominant moon/secondary moon
|
||
direction and render Tier-2 cascaded shadow depth from the resident caster
|
||
set.
|
||
3. Render the main world to the pack's world-colour intermediate, using
|
||
pack-selected pipeline variants to sample the shadow map where requested.
|
||
4. Preserve the established PView, punch/seal depth discipline, shared-alpha
|
||
ordering, particle ordering, and world transparency boundaries.
|
||
5. Generate screen-space sun occlusion/rays or, only while the shadow source is
|
||
the sun, shadow-map volumetrics.
|
||
6. Composite rays/shafts **before tonemapping**, so bloom sees them and the
|
||
filmic curve rolls them off instead of clipping them.
|
||
7. Apply tonemap, colour grade, and vignette to the main world image.
|
||
8. Continue with private portal/paperdoll/appraisal viewports and retained UI
|
||
on their existing path. They are not accidentally post-processed with the
|
||
main world.
|
||
|
||
## Delivery slices and acceptance
|
||
|
||
The slice labels below are local to this document. They are not phase IDs.
|
||
|
||
### Pre-moon checkpoint, Stage 1 acceptance, and Stage 2 start — 2026-08-22
|
||
|
||
Before the approved moon extension, all seven local slices (0–6) had production
|
||
implementations in the current worktree. A source-identical isolated clean
|
||
snapshot closed that sun-only reference-GPU physical matrix, and one physical
|
||
integrated-AMD Auto safe-fallback row was also present. Those artifacts remain
|
||
valid evidence for the exact binaries and sun-only scope they measured; they
|
||
are not moon-alignment, source-transition, current-worktree, or final user-
|
||
acceptance evidence.
|
||
|
||
Stage 1's automated implementation and validation are complete. The authored
|
||
sun/dominant-moon/secondary-moon resolver and its direction-versus-energy
|
||
handoff are present and covered without inferring physical quality from unit
|
||
tests, screenshots, or historical sun-only rows. The subsequent live ACE round
|
||
covered the owner-reported shadow visibility/configuration, temporal
|
||
pixelation/shimmer, frame-pacing/desktop responsiveness, selection/fullscreen
|
||
regressions, and matched indoor/outdoor exposure. After the exposure correction
|
||
the owner accepted the live result. The exact evidence and limits are recorded
|
||
in the [Stage 1 live-gate report](../research/2026-08-22-atmospheric-stage1-live-gate.md).
|
||
|
||
Current authored-celestial Stage 1 automated gate (2026-08-22):
|
||
|
||
- The shader compiler reports **24/24** Vulkan shader pairs ready. Incremental
|
||
regeneration expands only pack includes and preserves all 18 pre-campaign
|
||
retail SPIR-V artifacts byte-for-byte; the exact SHA-256 oracle and complete
|
||
source-manifest checks pass. All selected-celestial binding-6 modules expose
|
||
the 336-byte ABI v1 layout, including source kind at offset 320.
|
||
- Focused Release validation passes **344/344** App renderer tests, **30/30**
|
||
standalone SDK/pack-validator tests, **14/14** Core sky-loader tests, and
|
||
**48/48** MossTank tests. Both external Tier-2 samples embed and validate the
|
||
current selected-celestial shader ABI without App or Vulkan dependencies.
|
||
- The repository's forced locked restore passes. The complete Release solution,
|
||
including all source, tests, tools, and SDK samples, builds with **0 warnings
|
||
and 0 errors** after that restore.
|
||
- The repository-owned fresh-process hermetic gate passes
|
||
**14,928/14,928** tests with zero skips or failures across 14 assemblies;
|
||
`AcDream.App.Tests` contributes **5,823/5,823**. Evidence is under
|
||
`artifacts/atmospheric-rendering/stage1-moon-release-gate/`.
|
||
- The App total includes the 9,500-caster 256-frame zero-managed-allocation
|
||
steady-state fixture, warmed CPU/GPU sampling allocation gates, the complete
|
||
12-cycle Low/Medium/High/retail/resize/failure/recovery/frame-flight/
|
||
generation convergence fixture, and independent renderer/context/device
|
||
recreation. These prove the non-physical performance and lifetime contracts;
|
||
they do not claim physical frame pacing or image quality.
|
||
- A final path audit finds no source changes under `src/AcDream.Runtime`, no
|
||
physics or collision changes, and no changes to the retail GLSL sources or
|
||
tracked retail SPIR-V binaries. Pack-off production integration remains the
|
||
strict authoritative-path oracle.
|
||
|
||
The command-level record and evidence boundary are in the
|
||
[Stage 1 automated gate report](../research/2026-08-22-atmospheric-stage1-automated-gate.md).
|
||
|
||
Recorded pre-moon automated checkpoint (not a current moon-scope completion
|
||
claim):
|
||
|
||
- The repository-owned fresh-process Release test stage passes
|
||
**14,880/14,880** tests with zero skips or failures across 14 assemblies.
|
||
`AcDream.App.Tests` contributes **5,783/5,783**; campaign-focused App cases
|
||
cover descriptor/asset/SPIR-V
|
||
validation, pack-off/no-op invariants, atomic asynchronous candidate swaps,
|
||
runtime fallback, declared settings, Tier-1/Tier-2/Tier-2+ graph execution,
|
||
all headline caster classes, topology caching, exact animated transforms,
|
||
Low/Medium/High/Auto policy, diagnostics, and the pack UI.
|
||
- Headless plugin-session tests pass **6/6**, including rejection of a
|
||
render-pack-only request before its DLL is loaded.
|
||
- The SDK validator suite passes **26/26** and builds/validates the external
|
||
`AcDream.RenderPacks.NoOp`, `AcDream.RenderPacks.AtmosphericTier2`, and
|
||
`AcDream.RenderPacks.ShadowsOnlyTier2` samples without App or Vulkan
|
||
references.
|
||
- The production catalog is revisioned rather than frozen at startup. The same
|
||
composed controller/UI observes external registration, withdrawal, and
|
||
corrected re-registration; an active withdrawn pack retires at the next
|
||
frame boundary, persists retail fallback, releases its asset/context owners,
|
||
and does not retry the removed registration. Runtime package admission now
|
||
matches the SDK: exactly one public constructible render-pack entry point and
|
||
at least one live registration, with transactional rollback for malformed,
|
||
multiple, internal, zero-registration, and partially failing packages.
|
||
- The retained 9,500-caster warmed-frame fixture performs no second-frame
|
||
scene-index copy, topology rebuild, sort, or classification and allocates
|
||
zero managed bytes. Animated-static, live-dynamic, and equipped-child root
|
||
and part transforms refresh through cached IDs/slots with exact float bits.
|
||
- Render and screenshot diagnostics now publish exact accepted counts for
|
||
terrain commands, outdoor statics, buildings, animated statics, local
|
||
players, remote players, non-player creatures, other live dynamics, and
|
||
equipped children. These labels stop at the authoritative evidence boundary:
|
||
static DAT publication does not distinguish a tree from other outdoor
|
||
scenery, and create-object render metadata does not distinguish a hostile
|
||
monster from a non-hostile NPC creature. Diagnostics therefore report
|
||
`OutdoorStatics` and `NonPlayerCreatures`; they never infer tree or monster
|
||
identity from a mesh or ID.
|
||
- The recording-RHI long-cycle gate repeatedly crosses Low, Medium, High, and
|
||
retail selection; resize; injected candidate failure and explicit recovery;
|
||
both frame-flight slots; render-generation replacement; and final renderer
|
||
disposal. Pack resources, pipeline-format leases, texture slots, retained
|
||
transforms, receiver candidates, and registrations converge exactly. A
|
||
second fixture proves that device recreation is old-renderer/context/device
|
||
teardown followed by an independent fresh device and activation generation.
|
||
- Therefore the deterministic lifecycle implementation, recording-RHI
|
||
convergence, and fresh-device recreation definition are locally closed. The
|
||
executable connected route and its contract assertions are implemented for
|
||
select/disable/re-enable, exact resize, authored time/weather changes, and
|
||
fresh-process recreation, but a contract-tested route is not connected-world
|
||
evidence; its ACE-backed execution and artifacts remain open below.
|
||
- The complete Release solution, including all three SDK samples, the
|
||
validator, shader compiler/generated manifest, and repository tools, builds
|
||
with **0 warnings and 0 errors**. The current managed workspace could not
|
||
repeat the gate's locked-restore stage because it denies NuGet access to the
|
||
user-profile `NuGet.Config`; the explicit no-restore build and complete test
|
||
stage above are current, while locked-restore verification remains a
|
||
closeout-environment requirement rather than being reported as green here.
|
||
|
||
The corresponding durable source/test entry points are:
|
||
|
||
- public contracts and SDK:
|
||
`src/AcDream.Plugin.Abstractions/Rendering/`, `docs/render-packs/`,
|
||
`tools/RenderPackValidator/`, `samples/AcDream.RenderPacks.*`, and
|
||
`tests/AcDream.RenderPackValidator.Tests/`;
|
||
- activation, compatibility, Auto, diagnostics, and built-in graph:
|
||
`src/AcDream.App/Rendering/Packs/` and
|
||
`tests/AcDream.App.Tests/Rendering/Packs/`;
|
||
- moving authored-celestial cascades, casters, receivers, and retained topology:
|
||
`src/AcDream.App/Rendering/DirectionalShadow*.cs`,
|
||
`src/AcDream.App/Rendering/Packs/AuthoredCelestialShadowSource.cs`,
|
||
`src/AcDream.App/Rendering/Scene/DirectionalShadowCasterFrame.cs`,
|
||
`src/AcDream.App/Rendering/Wb/WbDrawDispatcher.DirectionalShadows.cs`, and
|
||
`tests/AcDream.App.Tests/Rendering/DirectionalShadow*` plus
|
||
`tests/AcDream.App.Tests/Rendering/Packs/AuthoredCelestialShadowSourceResolverTests.cs`;
|
||
- retained Display UI and headless boundary:
|
||
`src/AcDream.App/UI/Layout/ConfigOptionsPageController.cs`,
|
||
`tests/AcDream.App.Tests/UI/Layout/ConfigOptionsPageControllerTests.cs`, and
|
||
`tests/AcDream.Headless.Tests/HeadlessPluginSessionTests.cs`.
|
||
|
||
Machine-local offline/physical evidence currently present under
|
||
`artifacts/atmospheric-rendering/` is gate evidence, but it is not a substitute
|
||
for connected-world or project-owner acceptance:
|
||
|
||
- `smoke-retail-720p/` records the pack-off `retail/off` path with zero pack
|
||
resources, casters, cascades, or classification calls;
|
||
- `accept-shadow-morning-200m/`, `accept-shadow-afternoon-200m/`, and
|
||
`accept-shadow-morning-close/` contain fixed-camera moving-sun shadow
|
||
screenshots plus metadata for 9,498 resident casters and three cascades;
|
||
these pre-moon captures do not prove moon alignment or source transitions;
|
||
- `volumetric-valid-camera-500m/` contains a High-preset volumetric diagnostic
|
||
capture; it is not a performance acceptance row;
|
||
- `matrix-clean-snapshot-dense-linear-v20/` is the current complete AMD Radeon
|
||
RX 9070 XT physical matrix: **30/30 rows pass** across
|
||
retail/Low/Medium/High/Auto, 1080p/1440p/4K, and capped/uncapped pacing. The
|
||
actual worktree's 4,397 source files were copied and hash-verified into an
|
||
isolated clean snapshot at commit `4876c970`; the Release App product version
|
||
names that exact commit, source and binary identities match, and tracked
|
||
status is empty. Its 18 active enhanced rows each own exact 2,048-sample
|
||
CPU/receiver/GPU windows, 9,498 casters, and zero warmed classification calls.
|
||
Six rows are retail and six 4K Low/Medium/Auto rows are accepted
|
||
resource-unavailable fail-safe outcomes;
|
||
- `matrix-final-v16-exact-auto/` and the two `current-low-1080p-*-v20/`
|
||
captures retain the optimization's predecessor/reference trail; the clean
|
||
snapshot matrix above supersedes them as current reference-adapter evidence;
|
||
- all six retail rows record zero pack resources, passes, casters, cascades,
|
||
draws, or dispatches. The six unavailable 4K Low/Medium/Auto rows likewise
|
||
record zero pack work and pass their strict paired-default framebuffer
|
||
comparisons instead of rendering a half-enabled graph;
|
||
- `igpu-auto-safe-fallback-v7-paired/` records physical Auto behavior on the
|
||
integrated **AMD Radeon(TM) Graphics** adapter (Vulkan 1.4.315, driver
|
||
2.0.353). After 180 stable Low samples, Auto failed safe with the exact reason
|
||
`GPU p99 19.308 ms (budget 3.000 ms), CPU p99 0.534 ms (budget 0.500 ms),
|
||
resident GPU bytes 41648404 (budget 67108864)`. The published state is
|
||
`retail/off`, has zero pack resources or work, and retains that visible
|
||
reason. Its comparison against the paired time-matched retail artifact
|
||
`igpu-retail-current-v6-time-matched/`, using `sky-mask.png`, differs in only
|
||
**56 / 1,536,000 compared pixels**, a **0.003645833% (0.00365%) sky-masked
|
||
pixel difference**, below the 0.1% gate. This closes physical weak-adapter
|
||
safe fallback, not active Low performance on that adapter or the remaining
|
||
GPU matrix;
|
||
- `compare-retained-transform.json` records the retained-transform image
|
||
comparison used by the 9,500-caster steady-state gate.
|
||
|
||
Stage 1 project-owner gate:
|
||
|
||
- **PASS — accepted by the project owner on 2026-08-22.** The acceptance closes
|
||
Stage 1's physical-display and desktop-performance stop. It authorizes Stage
|
||
2; it is not a substitute for Stage 2's connected scenario, long-lifetime,
|
||
package lifecycle, additional physical-GPU, or final pack-off/pack-on rows.
|
||
|
||
Stage 2 machine-local closeout result (2026-08-22):
|
||
|
||
The exact commands, commits, metrics, artifacts, and evidence limits are in the
|
||
[Stage 2 connected and closeout report](../research/2026-08-22-atmospheric-stage2-connected-gate.md).
|
||
|
||
1. **PASS, except the external second-client row.** The connected graphical
|
||
route covered moving local players, known monster encounters
|
||
reported under the authoritative `NonPlayerCreatures` category, and equipped
|
||
children; landblock publication/demotion; clear, overcast and rain;
|
||
outdoor/interior/dungeon transitions; portal travel and reconnect. Capture
|
||
the implemented select/disable/re-enable, resize, authored sun/moon source
|
||
transitions and weather, and
|
||
fresh-process renderer/context/device-recreation assertions against a real
|
||
ACE session, proving exact resource convergence and no stale maps/owners.
|
||
Remote-player diagnostics remained zero because only one account/client was
|
||
available; a second connected client must close that evidence row.
|
||
2. **EXTERNAL HARDWARE GATE.** Repeat the current clean-source RX 9070 XT
|
||
pack-off/Low/Medium/High/Auto × 1080p/1440p/4K × capped/uncapped matrix on
|
||
every other supported physical GPU class. The integrated-AMD Auto-to-retail
|
||
artifact proves weak-adapter safe fallback only; it does not prove active Low
|
||
or the complete matrix on that adapter. Automated weak-GPU fixtures, one
|
||
fallback row, and one high-end reference adapter do not prove the remaining
|
||
physical rows.
|
||
3. **FINAL OWNER GATE.** Complete the visual matrix for Tier-1 neutral values and private-view/UI
|
||
isolation; rays at dawn/noon/dusk, behind-camera and occluded states;
|
||
foliage cutouts; moving animated shadows under sun and moon; indoor gating;
|
||
source-transition continuity; temporal pixelation/shimmer; bias/cascade seam
|
||
review; sun-only volumetric weather/occluder behavior; and pack-off
|
||
restoration.
|
||
4. **PASS.** External install/select/update/remove/fail/recover flows passed in
|
||
six fresh connected graphical processes. The nine-stop Medium lifetime route
|
||
passed with graceful shutdown, as did the deterministic 12-cycle and
|
||
fresh-device convergence fixtures.
|
||
5. **FINAL OWNER GATE.** Obtain explicit project-owner acceptance of the final pack-off and pack-on
|
||
visual/performance matrix before changing this document to shipped.
|
||
|
||
### Slice 0 — Contract, capability probe, and acdream-default no-op
|
||
|
||
**Implementation:** complete. The BCL-only v1 ABI, live revisioned plugin
|
||
discovery/catalog, retained Display selection, compatibility/cost summaries,
|
||
strict SDK-equivalent entry admission, asynchronous candidate preparation,
|
||
frame-boundary activation/withdrawal/fallback, registration-scoped no-retry,
|
||
stable diagnostics, no-op sample, and headless exclusion are present and
|
||
automated. The checked-in default-path oracle and RX 9070 XT physical pack-off
|
||
rows pass; connected lifetime evidence and the remaining supported physical GPU
|
||
classes stay open.
|
||
|
||
Define the versioned BCL-only descriptor/registry, manifest fields, semantic
|
||
bindings, pack discovery, Display selection, diagnostics, and atomic
|
||
activation/fallback transaction. Implement a no-op conformance pack only.
|
||
|
||
**Acceptance:** `acdream default (retail-faithful)` remains selected on clean and upgraded
|
||
installs; pack discovery allocates no GPU resources; the disabled run has the
|
||
same pass list, pipeline set, draw/dispatch counts, deterministic framebuffer
|
||
digests, and resource ledger as the pre-campaign baseline; malformed,
|
||
unsupported, missing, and shader-invalid fixtures all report one precise
|
||
reason and render acdream's default path without partial resources or retry loops; headless
|
||
hosts load no render assemblies or pack assets.
|
||
|
||
### Slice 1 — Tier-1 world-colour and filmic stack
|
||
|
||
**Implementation:** complete. The pack-owned main-world target, bloom chain,
|
||
ACES filmic pass, colour grade, vignette, declared neutral settings, resize
|
||
recreation, and private-viewport/UI placement are implemented and automated.
|
||
The RX 9070 XT 1080p/1440p/4K physical budget rows pass. Project-owner visual
|
||
acceptance and the remaining supported physical GPU classes stay open.
|
||
|
||
Add the main-world intermediate and implement bloom, ACES filmic tonemapping,
|
||
colour grade, and vignette through the pack API. Supply half/quarter-resolution
|
||
variants and preserve private viewports/UI.
|
||
|
||
**Acceptance:** every effect can be independently set to its neutral value;
|
||
the preset is deterministic across resize/recreate; UI, paperdoll, portal, and
|
||
appraisal surfaces retain their accepted colours; 1080p/1440p/4K captures show
|
||
no clipping, haloing at the world/UI edge, stale frame, or resource leak; the
|
||
slice meets its preset GPU/VRAM budget.
|
||
|
||
### Slice 2 — Tier-1 screen-space sun rays
|
||
|
||
**Implementation:** complete. Authored sun projection, the screen-space
|
||
occlusion mask, declared sun/day-group/weather policy, pre-tonemap ray
|
||
composition, and deterministic disabled gates are implemented and automated.
|
||
The connected dawn/noon/dusk, weather, behind-camera, occlusion, and edge-
|
||
flicker visual matrix remains open.
|
||
|
||
Project the existing authored sun position, build a screen-space occlusion
|
||
mask, and composite weather-driven crepuscular rays before tonemapping. This
|
||
slice deliberately has no shadow-map dependency.
|
||
|
||
**Acceptance:** clear dawn/dusk produces visible raking rays, noon makes them
|
||
vanish, overcast/rain mutes them, the sun behind the camera or fully occluded
|
||
produces none, and camera edges do not streak or flicker. The pack descriptor's
|
||
sun-elevation and `activeDayGroup` policy deterministically produces those
|
||
states without a second weather/clock owner. The exact same scene with Tier 1
|
||
disabled returns to the Slice-0 digest from acdream's default
|
||
retail-faithful renderer.
|
||
|
||
### Slice 3 — Tier-2 moving authored sun-and-moon dynamic shadows
|
||
|
||
**Implementation:** Stage 1 automated and project-owner live gates complete.
|
||
Camera-relative stabilized cascades,
|
||
outdoor gating, opaque and alpha-cutout casters, terrain/world receivers,
|
||
headline caster membership, exact current animated transforms, bounded
|
||
resident replay, GPU-flight ownership, and cached topology/dynamic-transform
|
||
refresh were present at the sun-only checkpoint. The approved authored
|
||
sun/dominant-moon/secondary-moon resolver and direction-versus-energy handoff
|
||
are now present, and focused plus complete fresh-process automated validation
|
||
pass. The project owner's 2026-08-22 live round accepted source alignment,
|
||
temporal stability, desktop responsiveness, and the final exposure correction.
|
||
Per-class diagnostics cover
|
||
terrain commands, outdoor
|
||
statics, buildings, animated statics, local/remote players, non-player
|
||
creatures, other live dynamics, and equipped children without inventing tree
|
||
or hostile-monster identity. Fixed-camera morning/afternoon artifacts are not
|
||
moon evidence; the live-gate result and its exact boundary are recorded in the
|
||
[Stage 1 live-gate report](../research/2026-08-22-atmospheric-stage1-live-gate.md).
|
||
The machine-local Stage 2 connected and closeout matrix passes. The external
|
||
second-client, additional-GPU, and final owner rows above remain open.
|
||
|
||
This is the campaign's headline slice. Add camera-relative cascades, opaque
|
||
and alpha-cutout caster variants, animated SSBO transforms, shadow receivers,
|
||
texel stabilization, outdoor gating, and weather/authored-directional-energy
|
||
control. Select the exact rendered direction of the visible above-horizon sun,
|
||
dominant haloed moon, or secondary moon according to the
|
||
[celestial source contract](../research/2026-08-22-dereth-celestial-shadow-sources.md),
|
||
while retaining retail's one `DirColor * DirBright` energy channel. Trees,
|
||
monsters, players, houses/buildings, terrain, and ordinary outdoor statics
|
||
participate through existing scene ownership.
|
||
|
||
**Acceptance:** in fixed-camera and live dawn/noon/dusk/night captures, shadows
|
||
align with and change direction/length under Dereth's authored sun and selected
|
||
dominant/secondary moon; overlap and no-source transitions are stable and do
|
||
not snap to an unrelated body. Walking players and monsters cast and
|
||
self-shadow from their current animated poses; foliage casts leaf/branch
|
||
cutouts rather than rectangles; houses and procedural trees retain shadows
|
||
through landblock publication/demotion without popping outside the chosen
|
||
cascade transition tolerance; indoor/dungeon captures have no outdoor
|
||
celestial directional shadow; portal/reconnect/device recreation leaves zero
|
||
stale maps or owners. Acne, Peter-panning, cascade seams, distant depth-bias
|
||
leaks, temporal pixelation/shimmer, and desktop performance pass the live user
|
||
gate and subsequent Stage 2 matrix; the dense-Arwic CPU submission and GPU
|
||
budgets pass.
|
||
|
||
### Slice 4 — Quality scaling and automatic compatibility
|
||
|
||
**Implementation:** complete. Low/Medium/High declarations, capability and
|
||
memory admission, preset cost summaries, retained Display controls, the
|
||
built-in Automatic checkbox, hysteretic Auto, diagnostics, asynchronous
|
||
off-side candidate preparation, and atomic stable-boundary swaps are present
|
||
and automated. The source-identical clean-snapshot RX 9070 XT matrix passes all
|
||
30 current rows after the Low dense-pose CPU optimization. The integrated-AMD
|
||
physical row proves that persistently over-budget Low returns Auto atomically to
|
||
retail with a visible reason and a paired-retail framebuffer match. Active Low
|
||
on that adapter and additional supported-adapter matrices remain open.
|
||
|
||
Land the Low/Medium/High presets, memory ceilings, capability-based preset
|
||
availability, stable cascade fitting, resize handling, and optional hysteretic
|
||
Auto selection. Auto may change resolution/range only at a stable frame
|
||
boundary and must expose its current choice.
|
||
|
||
**Acceptance:** every supported preset retains all headline caster classes;
|
||
weak-hardware fixtures select a valid lower preset or fail safely to acdream's
|
||
default renderer;
|
||
changing preset cannot leak, stall the render thread, invalidate streaming, or
|
||
leave mixed-resolution resources; the quality/performance table is populated
|
||
with measured physical-hardware results.
|
||
|
||
### Slice 5 — Tier-2+ volumetric shafts
|
||
|
||
**Implementation:** complete for the recorded sun-only scope. The declared
|
||
volumetric pass reuses directional-shadow depth only when the selected source
|
||
is the authored sun, consumes authored sun/weather/indoor inputs, composites
|
||
before tonemapping, and has independent quality/step settings and automated
|
||
failure gates. The reference-GPU low-sun 2,048-sample enabled/neutral A/B passes
|
||
its incremental cost target. Moon selection does not enable moon shafts. The
|
||
connected occluder/weather visual matrix and additional physical GPU classes
|
||
remain open.
|
||
|
||
Reuse the directional shadow map for world-space light shafts only while its
|
||
source is the authored sun. Drive density, strength, and colour from authored
|
||
sun/weather inputs and composite before tonemapping. A selected moon produces
|
||
directional shadows but no rays or volumetric shafts.
|
||
|
||
**Acceptance:** shafts respect terrain, trees, houses, and moving creatures;
|
||
clear low sun is strongest, overcast and indoor scenes are muted/off; disabling
|
||
shafts leaves Tier-2 shadow output unchanged; the incremental cost stays within
|
||
the Tier-2+ budget.
|
||
|
||
### Slice 6 — Pack SDK and campaign closeout
|
||
|
||
**Implementation:** SDK deliverables complete and the Stage 1 project-owner
|
||
gate passed on 2026-08-22. The v1
|
||
manifest schema, semantic binding table, compatibility/failure guide,
|
||
validator, built-in pack, and three buildable external samples are present and
|
||
automated. Connected graphical package lifecycle and long-run convergence pass.
|
||
The second-client remote-player row, remaining physical GPU classes, and final
|
||
project-owner acceptance remain open; the 30-row RX 9070 XT reference matrix is
|
||
complete.
|
||
|
||
Publish the manifest/schema, semantic binding table, sample no-op pack,
|
||
Atmospheric pack, compatibility diagnostics, authoring/validation tool, and
|
||
failure-handling guidance. Run the full automated, connected, physical-display,
|
||
performance, lifetime, portal, and screenshot matrix.
|
||
|
||
**Acceptance:** a clean external sample builds without App or Vulkan
|
||
references; install/select/update/remove/fail/recover flows work; pack-off
|
||
evidence from acdream's default retail-faithful renderer remains authoritative
|
||
and unchanged; all resource ledgers
|
||
converge after long play, reconnect, portal travel, pack disable, and device
|
||
recreation; the project owner accepts the visual matrix before the campaign is
|
||
declared shipped.
|
||
|
||
## Performance budget and measurement
|
||
|
||
The [measured pre-campaign baseline](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md#performance-baseline-and-the-binding-constraint)
|
||
is **519.7 FPS with CPU/GPU p50 of 1.869/1.096 ms**, and dense towns are
|
||
CPU-submission-bound. Fullscreen work may occupy currently idle GPU time, but
|
||
it is not treated as free. Shadow cascades must protect the CPU submission
|
||
path.
|
||
|
||
| Preset | Incremental GPU p50 / p99 at 1080p | Incremental render-CPU p50 / p99 | Pack-owned resident GPU memory |
|
||
|---|---:|---:|---:|
|
||
| Low | ≤ 2.0 / 3.0 ms | ≤ 0.15 / 0.50 ms | ≤ 64 MiB |
|
||
| Medium | ≤ 3.25 / 4.50 ms | ≤ 0.25 / 0.75 ms | ≤ 128 MiB |
|
||
| High | ≤ 4.50 / 6.00 ms | ≤ 0.35 / 1.00 ms | ≤ 256 MiB |
|
||
|
||
The current physical reference matrix is
|
||
`artifacts/atmospheric-rendering/matrix-clean-snapshot-dense-linear-v20/` on an
|
||
AMD Radeon RX 9070 XT (Vulkan 1.4.349, driver 2.0.395). The source-identical
|
||
isolated commit and Release binary both identify `4876c970`; tracked source
|
||
status is empty. All 30 rows pass. At capped 1080p, the exact 2,048-sample
|
||
windows are:
|
||
|
||
| Selection | Incremental render-CPU p50 / p99 | Inclusive GPU p50 / p99 | Resident pack memory |
|
||
|---|---:|---:|---:|
|
||
| Low | 0.108 / 0.164 ms | 0.900 / 1.002 ms | 39.719 MiB |
|
||
| Medium | 0.116 / 0.144 ms | 1.001 / 1.023 ms | 73.590 MiB |
|
||
| High | 0.121 / 0.145 ms | 1.240 / 1.273 ms | 113.556 MiB |
|
||
| Auto (settled High) | 0.122 / 0.146 ms | 1.211 / 1.222 ms | 113.556 MiB |
|
||
|
||
Every uncapped active row also passes. Across capped and uncapped active rows,
|
||
the maximum measured p50/p99 and resident memory are: Low 0.108/0.164 ms CPU,
|
||
1.070/1.080 ms GPU, 60.868 MiB; Medium 0.117/0.194 ms CPU, 1.152/1.163 ms GPU,
|
||
103.583 MiB; High 0.121/0.159 ms CPU, 2.237/2.252 ms GPU, 238.141 MiB; and Auto
|
||
0.122/0.166 ms CPU, 1.482/1.494 ms GPU, 145.856 MiB. All six retail rows record
|
||
zero pack resources/work. At 4K, Low needs 131,302,400 bytes and Medium/initial
|
||
Auto need 198,440,960 bytes, so those six capped/uncapped rows correctly report
|
||
`ResourceUnavailable`, create no pack resources/work, and pass their strict
|
||
paired-default framebuffer comparisons. This closes the current reference
|
||
adapter, not the connected receiver A/B route or other supported/weak physical
|
||
GPU classes.
|
||
|
||
Tier 2+'s separate low-sun physical A/B is recorded in
|
||
`artifacts/atmospheric-rendering/volumetric-performance-ab-1080p.json`. Both
|
||
runs pin High, 1080p uncapped, clear weather, 16.667° sun elevation, the same
|
||
50 m / 180° / 10° camera, 9,498 casters, four cascades, and exact 2,048-sample
|
||
windows. Enabling one volumetric draw over the neutral-strength run adds
|
||
**0.189 ms GPU p50 / 0.219 ms p99**, **0.009 ms CPU p50 / 0.007 ms p99**, and
|
||
4,147,200 resident bytes. The measured GPU p50 passes the Tier-2+ ≤0.40 ms
|
||
reference target; connected weather/occluder behavior and other adapters still
|
||
require their own rows.
|
||
|
||
acdream's default path has a stricter gate: zero new enhancement passes,
|
||
images, buffers, submissions, or shader variants, with CPU/GPU deltas within
|
||
the existing run-to-run noise envelope and deterministic reference captures
|
||
unchanged. `NoOpRenderPackProductionIntegrationTests` pins the pre-campaign
|
||
pass list, pipeline set, draw/dispatch tuple, framebuffer SHA-256, and complete
|
||
resource ledger; the matrix's six physical retail rows independently record
|
||
zero pack work at all three resolutions and both pacing modes.
|
||
|
||
Measurement protocol:
|
||
|
||
- Use existing asynchronous GPU timestamps and frame diagnostics. Never add a
|
||
`glFinish`/device-idle-style measurement fence to the frame loop.
|
||
- Runtime Auto compares the declared incremental CPU budget with pack-added
|
||
target-preparation, shadow, post, and volumetric recording only. The complete
|
||
enhanced main-world receiver recording is retained separately as an absolute
|
||
CPU diagnostic; it is not itself an incremental delta. GPU accounting remains
|
||
conservatively inclusive of the complete enhanced receiver pass and every
|
||
resolved pack pass, exactly once after asynchronous resolution. Identical
|
||
pack-off/on runs remain the authority for the final receiver CPU delta and
|
||
the complete physical incremental A/B result.
|
||
- Run capped and uncapped Release builds; record CPU/GPU p50, p95, and p99,
|
||
FPS, draw/dispatch submissions, shadow-caster count, cascade draw count,
|
||
transient/retained GPU bytes, and process working/private memory.
|
||
- Compare pack off, Low, Medium, and High with identical camera paths, render
|
||
resolution, active day group, authored celestial/time keyframe, entity set,
|
||
and warmed residency.
|
||
- Cover pinned dense Arwic, a foliage-heavy outdoor route, a building cluster,
|
||
moving-player/monster combat, dawn/noon/dusk/night plus sun/moon/no-source
|
||
transitions, clear/overcast/rain, a dungeon, portal travel, resize, reconnect,
|
||
and a long lifetime run.
|
||
- Measure 1920x1080, 2560x1440, and 3840x2160 on each supported physical GPU
|
||
class. Report—not hide—unavailable presets.
|
||
- No cascade may rerun CPU PView/portal traversal or issue per-object draws.
|
||
The pass records CPU classification calls and submission counts so this is
|
||
an enforced gate, not an architectural hope.
|
||
- Pipeline creation and pack validation occur before atomic activation. Normal
|
||
play may not hitch on first shadow, weather, caster, or quality use.
|
||
|
||
## Quality scaling for weak hardware
|
||
|
||
These are starting envelopes to validate, not asset or world guarantees.
|
||
Distances are metres and are always clamped to current resident world data.
|
||
|
||
| Setting | Bloom/rays | Directional shadows | Volumetric shafts | Approx. depth-map memory at 32-bit depth |
|
||
|---|---|---|---|---:|
|
||
| Off / acdream default | Off | Off | Off | 0 MiB |
|
||
| Low | Quarter resolution | 2 × 768² cascades, about 72 m maximum reach | Off by default | 4.5 MiB |
|
||
| Medium | Half resolution | 3 × 1536² cascades, about 144 m maximum reach | Quarter resolution | 27 MiB |
|
||
| High | Half/full as measured | 4 × 2048² cascades, about 240 m maximum reach | Half resolution | 64 MiB |
|
||
|
||
Additional scaling rules:
|
||
|
||
- Prefer reducing cascade count, shadow resolution, reach, bloom/ray
|
||
resolution, and sample count before removing a feature's semantic
|
||
correctness.
|
||
- Preserve alpha-tested foliage and animated transforms at every shadow
|
||
quality. A cheaper preset may look softer or end sooner; it may not turn a
|
||
tree into a rectangle or freeze a monster's shadow.
|
||
- Clamp resource dimensions and bytes before allocation. A capability probe
|
||
that cannot support Low disables the pack and explains why.
|
||
- Preset availability uses the selected Vulkan adapter's probed 2-D image and
|
||
array-layer limits. Optional pack memory receives at most one eighth of its
|
||
device-local heap, capped at 256 MiB resident and 512 MiB transient; Auto
|
||
starts at Low when Medium is unavailable and acdream's default remains the fallback if
|
||
Low cannot fit.
|
||
- Optional Auto quality uses long hysteresis and stable frame-boundary swaps;
|
||
it never oscillates cascade layouts frame to frame. If Low stays over its
|
||
declared runtime GPU/CPU/resident budgets for 180 stable samples, Auto
|
||
retires the complete pack and returns to acdream's default with the measured
|
||
and declared limits in the visible failure reason.
|
||
- 4K defaults may choose lower post-process resolution because Tier 1 pays
|
||
approximately four times the 1080p pixel workload.
|
||
|
||
## Constraints and traps
|
||
|
||
This list carries forward every item in the findings' measured
|
||
[shadow-specific constraints](../research/2026-08-21-terrain-and-atmospheric-rendering-findings.md#shadow-specific-constraints)
|
||
and adds the current renderer's ownership and lifecycle boundaries.
|
||
|
||
1. **The renderer is the shipped pass-based Vulkan RHI.** Design against
|
||
`IGpuDevice` / `IGpuFrame` / `IGpuPassEncoder` and explicit pass/pipeline
|
||
descriptions. Do not revive an OpenGL backend or build a parallel renderer.
|
||
2. **The current PView graph is authoritative.** Shadow and atmosphere passes
|
||
consume its retained scene; they do not introduce a competing visibility
|
||
owner or change punch/seal, shared-alpha, particle, or private-viewport
|
||
ordering.
|
||
3. **CPU submission is the limiting dimension.** Reusing the full bounded
|
||
resident caster set is preferable to CPU-reculling it per cascade. GPU
|
||
culling is the only planned escalation.
|
||
4. **Alpha-tested foliage needs sampling and discard.** Reusing the existing
|
||
empty `portal_depth` fragment shader would cast solid tree rectangles.
|
||
5. **Animated casters use the existing N.5 SSBO transforms.** A second pose,
|
||
animation tick, or entity owner is forbidden.
|
||
6. **Indoors has no outdoor celestial directional shadow.** Dungeon/EnvCell
|
||
authored ambient and local lighting wins; outdoor sun/moon directional
|
||
shadows, sun rays, and sun shafts are gated off.
|
||
7. **Cascades are camera-relative and streaming-bounded.** They may not use a
|
||
fixed Dereth-wide extent, request landblocks, retain retired generations, or
|
||
draw stale portal destinations.
|
||
8. **Depth bias is specified in meaningful eye/world units.** A constant NDC
|
||
bias spans approximately `b*d²/near` metres of eye depth at distance and can
|
||
recreate issue #129's door-shaped holes through hills. Bias, normal offset,
|
||
cascade projection, near/far fitting, and reversed-depth conventions must be
|
||
tested together at near and far ranges.
|
||
9. **“Shadow” is an overloaded project term.** Existing `shadow_objects` and
|
||
`CPhysicsObj::add_shadows_to_cells` are collision registration, not light
|
||
shadows. New names use `DirectionalShadowMap`, `ShadowCaster`, or
|
||
`CelestialDirectionalShadow`; never generic `ShadowObject`.
|
||
10. **Authored celestial position, directional energy, and weather are
|
||
inputs.** Do not invent another celestial clock, light-energy channel,
|
||
weather state, or hard-coded dawn/noon schedule. The directional map uses
|
||
the visible above-horizon sun/dominant moon/secondary moon's exact rendered
|
||
direction but retail's single interpolated `DirColor * DirBright` colour/
|
||
energy channel, per the
|
||
[celestial source research](../research/2026-08-22-dereth-celestial-shadow-sources.md).
|
||
Rays and shafts remain sun-only and use the pack's declared sun-elevation
|
||
curve and categorical `activeDayGroup` mapping. The decomp evidence proves
|
||
the category reaches the frame, not an authored numeric ray intensity, so
|
||
the enhancement mapping must remain explicit pack policy.
|
||
11. **Atmosphere ordering is deliberate.** Rays/shafts composite before
|
||
tonemapping; retained UI and private viewports remain outside main-world
|
||
post-processing.
|
||
12. **Transparency remains ordered.** The pack cannot flatten the retail
|
||
world-alpha queue into an unordered shadow/post pass. Truly translucent
|
||
surfaces cast no opaque shadow until separately designed.
|
||
13. **Generation and GPU-flight lifetimes remain exact.** Pack images,
|
||
descriptors, and pipelines retire through existing fences and converge on
|
||
disable, resize, portal, reconnect, reset, failure, and device recreation.
|
||
14. **4K is a distinct performance row.** Tier-1 effects scale with pixels;
|
||
passing at 1080p is not evidence for 4K.
|
||
15. **Do not repeat closed investigations.** High-res DAT precedence is not
|
||
dropping overrides, AC detail textures are colour/alpha rather than normal
|
||
maps, and the engine's historical DOT3 capability does not turn those
|
||
assets into PBR inputs; these points are already falsified in the findings.
|
||
16. **Caster evidence must not exceed source identity.** Diagnostics separately
|
||
count terrain commands, outdoor statics, buildings, animated statics,
|
||
local/remote players, non-player creatures, other live dynamics, and
|
||
equipped children. Outdoor statics include trees but have no authoritative
|
||
tree discriminator; non-player creatures include monsters but have no
|
||
render-only hostile-monster-versus-NPC discriminator. Visual/connected
|
||
acceptance must name those limits instead of fabricating narrower counts.
|
||
|
||
## What this does NOT do
|
||
|
||
- It does **not** change acdream's default retail-faithful rendering path, its
|
||
expected output, or its authority in fidelity tests.
|
||
- The Atmospheric shader pack does **not** own or depend on #226 detail
|
||
texturing or the terrain-normal parity correction. Those remain separate
|
||
Track A ports even though the project owner authorized their implementation
|
||
in the same worktree.
|
||
- It does **not** add PBR or fabricate normal, roughness, metalness, or material
|
||
maps that AC's assets do not contain.
|
||
- It does **not** change terrain vertices, collision triangles, walkability,
|
||
slope response, physics shadow lists, movement, projectiles, or any Runtime
|
||
physics/collision owner.
|
||
- It does **not** change gameplay rules/state, network messages or ordering, or
|
||
any Runtime gameplay/network owner.
|
||
- It does **not** extend view distance, streaming radius, landblock residency,
|
||
or PView visibility to find more shadow casters.
|
||
- It does **not** add an indoor sun or replace authored EnvCell/local lights.
|
||
- It does **not** turn moon texture brightness or mesh luminosity into another
|
||
world-light energy channel, and it does not produce moon rays or moon shafts.
|
||
- It does **not** post-process retained UI or silently restyle private
|
||
paperdoll, appraisal, or portal viewports.
|
||
- It does **not** promise that every pack or quality preset runs on unsupported
|
||
hardware; compatibility failure is explicit and safely returns to acdream's default renderer.
|
||
- Campaign AR does **not** outrank active M4 gameplay work. The project owner's
|
||
explicit reprioritization authorizes this campaign without changing M4's
|
||
milestone priority; #268 + TS-8 are already complete and retired.
|
||
|
||
## Completion gate
|
||
|
||
The design, implementation, Stage 1 owner gate, and every available
|
||
machine-local Stage 2 connected, performance, lifetime, package, shader, build,
|
||
and complete-test gate are complete. The campaign becomes **shipped** only
|
||
after the second-client remote-player row, remaining physical-hardware rows,
|
||
and final visual gates above pass and the project owner accepts both sides of
|
||
the final matrix:
|
||
|
||
- **pack off:** unchanged output, performance, ownership, and lifecycle from
|
||
acdream's authoritative default retail-faithful renderer; and
|
||
- **pack on:** moving authored sun-and-moon directional shadows from trees,
|
||
monsters, players, and buildings; sun-only rays/shafts; scalable atmosphere,
|
||
safe compatibility fallback, measured budgets, and clean long-lived resource
|
||
convergence.
|