acdream/docs/plans/2026-08-21-atmospheric-rendering.md
Erik 132395e6f7 fix #425: pack resident budget is a 1080p ceiling that scales with pixel count; an explicit Apply retries a failed selection
Live Holtburg at 2560x1440: the Low preset needed 67,368,164 resident bytes
(screen-sized HDR/depth/ray targets are 44 MB of that) against an absolute
64 MiB ceiling that had only been validated at 1080p, so Options -> Apply
fell back to the default path; every later Apply was then refused by the
controller's failure memo, which treated the user's deliberate choice like
automatic re-activation.

RenderPackResidentBudget.Effective scales the declared 1080p figure by the
viewport's pixel-count ratio (never below 1), still capped by the hardware
MaxPackResidentBytes; both pack graphs use it and the performance-matrix
tool judges its resident column by the same rule (contract test updated).
RenderPackController.Request gains explicitUserChoice, which clears the
memo for that selection; RenderPackSelectionBinding passes it on every
display edge (Apply, including resolution changes) and keeps the memo for
the startup request.

Tests: RenderPackResidentBudgetTests (1080p/720p keep the declared
ceiling, 1440p = 16/9x, 4K = 4x, hardware cap wins, zero extent rejected);
controller explicit-retry; the binding test now proves the user's next
Apply activates once the cause is gone. App hermetic lane 6,068/0 (Release).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 10:00:11 +02:00

58 KiB
Raw Blame History

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 distinct-account 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 on a distinct ACE account, 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, especially the measured renderer baseline and the requested tier model. The approved celestial identity, priority, transform, and direction-versus- energy contract are pinned by the Dereth celestial shadow-source research.

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
0 Weather-driven foliage wind (Campaign VM VM6): procedural-scenery trees/bushes lean, branch-swing, and flutter; their directional-shadow casters apply the identical displacement so the shadow moves with the leaf Shader ABI v2 (AtmosphericFrame gains uAtmosphereClockWind/uAtmosphereWindAmplitude); the existing ProceduralSceneryIdAllocator entity-id namespace for classification ~0.05 ms (near-zero; ~25 ALU per displaced vertex, zero CPU cost, zero extra draw submissions — an early-out uint AND gates every non-foliage vertex)
1 Bloom, ACES filmic tonemap, colour grade, vignette Main-world colour intermediate and fullscreen passes 0.350.80 ms
1 Screen-space sun rays (crepuscular) Authored sun screen position plus an occlusion mask; no shadow maps 0.200.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.503.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.150.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.

Foliage wind (Tier 0, Campaign VM VM6). Deliberately numbered below Tier 1: it needs no fullscreen pass, no colour intermediate, and no shadow infrastructure of its own — only the shader ABI v2 clock/wind block and the per-batch classification bits BatchData.flags already carries. It composes with every other tier (Tier 2's shadow casters read the same displacement so a swaying tree's shadow tracks it) and, uniquely among these tiers, is cheap enough that a future default-on consideration is plausible; today it ships opt-in with the rest of the atmospheric pack, gated by wind-enabled.

Tier 2 headline: Dereth's moving authored sun-and-moon shadows

The measured renderer state 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. 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:

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.

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 (06) 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.

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 under the repository's hermetic lane filter (Manual/Timing/Live/ InstalledDat/Diagnostic lanes excluded; a raw dotnet test AcDream.slnx reports those lanes as skips/failures by design — VM4 correction); 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.

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 (hermetic lane filter, as above). 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. This historical checkpoint could not repeat locked restore because that managed workspace denied NuGet access to the user-profile NuGet.Config; the later Stage 1 moon gate and final Stage 2 gate supersede that limitation and both report forced locked restore green.

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.

  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. The implemented two-client gate proved the observer login and movement, but ACE rejected the concurrent primary login when both used the available account. The gate now requires dedicated observer environment credentials, keeps them out of its artifacts, and permits independent character indexes; a distinct-account connected run must close the authoritative nonzero RemotePlayers 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 and graphical package evidence now pass. 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.

Campaign VM VM3 (2026-08-22) moved the post stack to linear light: every world/ray/volumetric read is decoded with the 2.2 display assumption; the bloom intermediate is already linear (decoded once at extraction, so downstream blur/composite reads need no further decode). Tonemap/grade/ vignette run in linear and the result is re-encoded; the post stack's neutral settings are a numerical identity (measured on a real frame at Campaign VM VM3: ≤1 LSB on 99.99 % of pixels; 95 foliage-silhouette pixels — 58 isolated — differ by up to 73 LSB from cutout-edge rasterization between two separate client runs, none on any surface).

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. Connected time/weather transitions pass; physical-display acceptance for dawn/noon/dusk, behind-camera, occlusion, and edge-flicker behavior remains in the final owner visual matrix.

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. 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, 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. Connected weather/lifecycle transitions pass; physical-display occluder/weather acceptance in the final owner 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 distinct-account 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 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 at 1080p (scales with pixel count — RenderPackResidentBudget.Effective, #425)
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 pass list, pipeline set, draw/dispatch tuple, framebuffer SHA-256, and resource ledger of a 2x2 synthetic, one-draw composition fixture on a recording device that does not rasterize — it proves the controller arm adds nothing to that shape, not that the production frame is unchanged. The matrix's six physical retail rows record zero pack work at all three resolutions and both pacing modes. The actual pack-off pixel and production-performance invariance against the pre-campaign build 6c79d35c was established later by Campaign VM slice VM0 (report, corrected 2026-08-22).

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 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. 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 requirement ledger and the exact remaining external rows are consolidated in the Campaign AR completion audit.

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 distinct-account 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.