39 KiB
World Renderer
Metadata
| Field | Value |
|---|---|
| Status | Partial |
| Target/work package | M00 baseline; M01-RND-STREAMING-FOCUS-001; M01-QAR-SERVER-SPAWN-RENDERER-001; M03 facade/planner/scheduler/internal-access/ground/environment/entity packages; M03 terrain cache/LOD/geometry-queue packages |
| Owners | Renderer workstream / milestone integrator |
| Last verified | Worktree work/sindo-main-codex/m03-terrain-chunk-queue, 2026-07-16 |
| Profiles/capabilities | Performance, Balanced, High, Custom; Blizzlike fidelity incomplete |
Purpose
Загрузить и визуализировать мир WoW 3.3.5a вокруг streaming focus: terrain, ADT placements, M2, WMO, liquids, sky/light и character/world presentation experiments. Система должна скрывать I/O/parsing/finalization latency за prewarm и per-frame budgets.
Non-goals
- Не владеет gameplay/world authoritative state.
- Не читает network packets или server DB.
- Не определяет player input/movement rules.
- Не является Content Project или editor source of truth.
- Текущий module не заявляет визуальное соответствие
1:1; gaps ведутся в../../RENDER.md.
Context and boundaries
flowchart LR
Player[Player or spectator Node3D] --> Adapter[Explicit source adapter]
Editor[Editor viewport adapter] --> Focus[StreamingFocus]
Capture[Capture tool] --> Adapter
SpawnFixture[Pinned server spawn fixture] --> SpawnManifest[Spawn render manifest]
SpawnManifest --> Capture
Adapter --> Focus
Focus --> Facade[WorldRenderFacade]
Facade --> Loader[StreamingWorldLoader internal]
Loader --> Planner[StreamingTargetPlanner]
Planner --> TargetPlan[StreamingTargetPlan]
TargetPlan --> Loader
Loader --> Budget[RenderBudgetScheduler]
Assets[Extracted WDT/ADT/M2/WMO/BLP] --> Native[Native loaders]
Cache[Baked terrain/M2/WMO caches] --> Loader
Loader --> TerrainCache[TerrainQualityMeshCache]
TerrainCache --> Loader
Loader --> ChunkLod[TerrainChunkLodPlanner]
ChunkLod --> Loader
Loader --> ChunkQueue[TerrainChunkGeometryQueuePlanner]
ChunkQueue --> Loader
Native --> Parsed[Parsed tile/model data]
Parsed --> Loader
Loader --> Scene[SceneTree nodes]
Loader --> RS[RenderingServer RIDs/MultiMesh]
EnvironmentState[World time producer] --> EnvironmentSnapshot[WorldEnvironmentSnapshot]
EnvironmentSnapshot --> Facade
Facade --> SkyController[WowSkyController]
Sky[DBC sky/light data] --> SkyController
SkyController --> Scene
EntityState[Entity visual read model] --> EntitySnapshot[EntityPresentationSnapshot]
EntitySnapshot --> Facade
Facade --> EntityPresenter[WorldEntityPresenter]
EntityPresenter --> Scene
Allowed dependencies:
- native format loaders;
- render builders/material helpers;
- immutable/cached render resources;
- renderer configuration and focus;
- Godot rendering/scene APIs.
Forbidden dependencies:
- packet codecs/world session;
- gameplay reducers/quest/combat state;
- runtime UI Controls;
- direct TrinityCore/AzerothCore database access.
Public API
Runtime, capture and probe callers use WorldRenderFacade for focus, immutable
environment/entity presentation input, metrics and rendered-ground diagnostics.
StreamingWorldLoader, WowSkyController and WorldEntityPresenter remain
internal scene implementations.
Gameplay modules and Godot EditorPlugin package sources are repository-gated
from externally reading/writing loader-private queue, task, cache and tile-state fields.
| Symbol | Kind | Purpose | Thread/lifetime | Errors |
|---|---|---|---|---|
map_name |
Exported property | WDT/map directory name | Set before world load | Missing WDT produces diagnostic/empty world |
extracted_dir |
Exported property | Root of legally extracted client data | Session lifetime | Missing files reported per loader path |
StreamingFocus |
Immutable value | Typed Godot-basis position without Node/Camera dependency | Any thread; caller-owned reference | Null position is a caller contract violation |
WorldRenderFacade.streaming_focus_source_path |
Exported adapter property | Samples any explicit Node3D source into StreamingFocus |
Main thread, scene lifetime | Missing/wrong node warns once and retains prior focus |
WorldRenderFacade.set_streaming_focus |
Public method | Accepts focus from app/editor/tool composition | Main thread/session | Missing internal renderer is diagnosed; no state is duplicated |
WorldRenderFacade.refresh_streaming_focus |
Public method | Samples configured source and delegates existing refresh thresholds | Main thread/session | Returns false when dependency/focus is unavailable |
WorldRenderFacade.renderer_metrics_snapshot |
Public method | Returns a deep-detached queue/cache/activity snapshot | Main thread/caller-owned result | Missing/invalid implementation result returns empty snapshot with diagnostic |
WorldRenderFacade.sample_ground_height |
Public read-only query | Samples already loaded render terrain at a typed Godot world position | Main thread; immutable caller-held result | Stable unavailable code for missing mesh/intersection/facade; not gameplay authority |
WorldRenderFacade.renderer_ground_query_snapshot |
Public diagnostic query | Returns ground height plus detached tile/readiness context without exposing mutable state | Main thread; caller-owned deep copy | Missing/invalid renderer returns empty snapshot with diagnostic |
WorldEnvironmentSnapshot.at_time_of_day |
Immutable value factory | Normalizes a finite authoritative time into [0, 24) hours |
Any thread; caller-held value | Non-finite input creates invalid value with environment_time_not_finite |
WorldRenderFacade.apply_environment_snapshot |
Public command | Delegates exact world time to the scene-owned DBC sky controller | Main thread; snapshot remains caller-owned | Returns false for invalid input or missing/incompatible controller |
WorldRenderFacade.streaming_world_loader_path |
Internal adapter property | Resolves the existing implementation without exposing it to consumers | Main thread, scene lifetime | Missing method/path produces one diagnostic until recovery |
WorldRenderFacade.world_environment_controller_path |
Internal adapter property | Resolves the existing WowSkyController without exposing it to consumers |
Main thread, scene lifetime | Missing method/path produces one diagnostic until recovery |
EntityPresentationSnapshot.create |
Immutable value factory | Validates contract-v1 identity, typed position, visual path, yaw, scale and visibility | Any thread; caller-owned | Stable invalid code; never mutates scene |
WorldRenderFacade.present_entity |
Public command | Idempotently creates/updates/replaces one session entity visual | Main thread/session | Returns false for invalid input, missing service or visual load/type failure |
WorldRenderFacade.remove_entity |
Public command | Removes one known session entity visual | Main thread/session | Invalid/unknown identity returns false |
WorldRenderFacade.entity_presentation_snapshot |
Public diagnostic query | Returns detached scalar entity inventory | Main thread/caller-owned copy | Missing/invalid service returns empty dictionary with diagnostic |
WorldRenderFacade.world_entity_presenter_path |
Internal adapter property | Resolves renderer-owned entity visual service | Main thread/scene lifetime | Missing methods/path produces one diagnostic until recovery |
camera_path |
Exported property | Camera used only by optional automatic overview positioning | Main thread, scene lifetime | Missing camera skips automatic positioning |
quality_preset |
Exported property | Applies renderer budgets/radii | Before/at runtime depending property | Invalid combination should be diagnosed |
runtime_stats_enabled |
Exported property | Enables periodic performance snapshot | Runtime mutable | Logging overhead only |
hitch_profiler_enabled |
Exported property | Enables named hitch sections | Runtime mutable | Logging overhead only |
TerrainQualityMeshCache.store/restore/clear |
Internal terrain service | Owns admitted full-quality revisit Mesh references and LRU | Renderer thread/map session | Rejected/missed entry leaves loader fallback unchanged |
TerrainChunkLodPlanner.plan |
Internal pure terrain query | Maps populated parsed chunk indices to desired LOD 0/1/2 | Synchronous per target refresh | Invalid/disabled input returns empty for existing tile-LOD fallback |
TerrainChunkGeometryQueuePlanner.plan |
Internal pure terrain query | Produces chunk create/remove requests from current and desired state | Synchronous per queue rebuild | Invalid focus returns empty arrays |
Публичным contract не считаются StreamingWorldLoader methods/properties,
внутренние dictionaries, queues, job records и generated node names. Scene-owned
loader configuration remains transitional composition data, not a caller API.
Inputs and outputs
| Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime |
|---|---|---|---|---|---|
| Input | StreamingFocus |
Player/spectator/editor/capture adapter | WorldRenderFacade |
Immutable caller value | Main thread/session |
| Input | Focus-source NodePath |
Runtime/test scene composition | WorldRenderFacade source adapter |
Scene-owned node, sampled position | Main thread/scene lifetime |
| Input | Ground-query GodotWorldPosition |
Renderer probe/future adapter | WorldRenderFacade |
Immutable caller-held value | One main-thread query |
| Input | WorldEnvironmentSnapshot |
World-state/capture adapter | WorldRenderFacade / WowSkyController |
Immutable caller-held value; not retained | One main-thread update |
| Input | EntityPresentationSnapshot |
Future world-state/preview adapter | WorldRenderFacade / entity presenter |
Immutable caller-held full visual snapshot | One main-thread present/update |
| Input | EntityId removal command |
Future entity registry/adapter | WorldRenderFacade / entity presenter |
Immutable session-local value | One main-thread removal |
| Input | Map/configuration | Scene/app/editor | StreamingWorldLoader |
Caller config, copied/read | Main thread/session |
| Input | WDT/ADT/M2/WMO/BLP bytes | Extracted asset repository | Native loaders/builders | Loader result owns parsed data | Worker or controlled load |
| Input | Baked resources | Cache build tools | Streamer/builders | Shared immutable resource/cache entry | Session/cache lifetime |
| Test input | Server-spawn render manifest | Coordinate fixture/verifier | Checkpoint capture tool | Repository-owned diagnostic data | Test-process lifetime |
| Output | StreamingTargetPlan |
StreamingTargetPlanner |
Streamer queue/state apply | Immutable ephemeral value | One refresh |
| Internal control | Per-frame lane limits and boolean permits | Streamer configuration / RenderBudgetScheduler |
Ordered streamer drains | Scheduler-owned counters | Main thread/frame |
| Internal cache | Full-quality terrain Mesh/source | Loader terrain upgrade / TerrainQualityMeshCache |
Revisited tile state | Cache-retained Mesh reference | Map session until eviction/reset |
| Internal plan | Parsed chunks, typed focus and immutable chunk-LOD policy | Loader / TerrainChunkLodPlanner |
Loader desired state | Fresh dictionary; no retained resources | One target refresh |
| Internal plan | Current/desired chunk state and typed focus | Loader / TerrainChunkGeometryQueuePlanner |
Loader chunk queues | Fresh request arrays; no retained resources | One queue rebuild |
| Output | Desired tile/detail operations | Streamer plan application | Finalize queues | Loader-owned | Cross-frame |
| Output | Terrain/M2/WMO/liquid instances | Loader/builders | Godot world/renderer | Loader/world owner | Main-thread attach |
| Output | Detached renderer metrics | WorldRenderFacade |
Capture/baseline tools | Caller-owned deep copy | On demand |
| Output | RenderedGroundSample |
WorldRenderFacade/loaded terrain |
Renderer diagnostics | Immutable caller-held value | One query |
| Output | Detached rendered-ground snapshot | WorldRenderFacade |
Terrain-height probe | Caller-owned deep copy | One query |
| Output | Entity visual Node3D subtree | WorldEntityPresenter |
SceneTree/viewport | Presenter-owned child | Until replace/remove/teardown |
| Output | Detached entity inventory | WorldRenderFacade |
Diagnostics/tests | Caller-owned deep copy | One query |
| Output | Logs/diagnostics | Hitch/stat instrumentation | Logs/baseline tools | Immutable records | Periodic/frame |
| Test output | Diagnostic spawn marker and cold/warm PNGs | Checkpoint capture tool | Human/integrator review | SceneTree marker; user:// files |
One capture process |
Side effects:
- reads extracted files and generated caches;
- creates/frees scene nodes, meshes, materials, MultiMeshes and RIDs;
- submits worker tasks;
- mutates shader globals/environment through render/sky paths;
- writes logs and baseline captures through tools.
Data flow
flowchart TD
PlayerSource[Player/spectator Node3D] --> A[Explicit scene adapter]
C[Capture camera] --> A
SF[Pinned server spawn] --> SM[Validated spawn manifest]
SM --> C
SM --> Marker[Renderer-native origin marker]
E[Editor viewport] --> EA[Editor adapter]
A --> F[StreamingFocus]
EA --> F
F --> RF[WorldRenderFacade]
RF --> Planner[StreamingTargetPlanner]
Planner --> T[StreamingTargetPlan apply]
WDT[WDT tile catalog] --> Planner
T --> Q[Tile load queue]
Q --> Parse[Worker parse/cache load]
Parse --> R[Result queues]
R --> TerrainCache[TerrainQualityMeshCache store]
TerrainCache --> Revisit[Revisited tile state restore]
R --> ChunkLod[TerrainChunkLodPlanner]
ChunkLod --> DesiredChunkLod[Desired chunk LOD state]
DesiredChunkLod --> ChunkQueue[TerrainChunkGeometryQueuePlanner]
ChunkQueue --> B
R --> B[RenderBudgetScheduler permits]
B --> Terrain[Terrain attach/upgrade]
B --> M2[M2 group/MultiMesh attach]
B --> WMO[WMO instance/group attach]
B --> Liquid[Liquid attach]
Loaded[Loaded terrain Mesh and Transform] --> Ground[Facade ground query]
Ground --> GroundSample[RenderedGroundSample / detached diagnostics]
WorldTime[Authoritative/test time] --> EnvironmentSnapshot[WorldEnvironmentSnapshot]
EnvironmentSnapshot --> RF
RF --> SkyController[WowSkyController]
DBC[Light/Area/Skybox DBC] --> SkyController
SkyController --> World
EntityReadModel[Entity visual read model] --> EntitySnapshot[EntityPresentationSnapshot]
EntitySnapshot --> RF
RF --> EntityPresenter[WorldEntityPresenter]
EntityAsset[PackedScene path] --> EntityPresenter
EntityPresenter --> World
Terrain --> World[Godot world]
M2 --> World
WMO --> World
Liquid --> World
Marker --> World
F --> Eviction[Eviction/retention decisions]
Eviction --> World
Lifecycle/state
stateDiagram-v2
[*] --> Initializing
Initializing --> WaitingForFocus: WDT/catalog/config ready
Initializing --> Degraded: missing loaders/data/cache
WaitingForFocus --> Streaming: valid StreamingFocus
Streaming --> Streaming: load/finalize/evict ticks
Streaming --> WaitingForFocus: world reset without replacement focus
Streaming --> SwitchingMap: map/focus reset
SwitchingMap --> Initializing
WaitingForFocus --> ShuttingDown
Degraded --> ShuttingDown
Streaming --> ShuttingDown
ShuttingDown --> [*]
Main sequence
sequenceDiagram
participant Source as Player/Editor/Capture source
participant Focus as StreamingFocus adapter
participant Facade as WorldRenderFacade
participant Stream as StreamingWorldLoader internal
participant Planner as StreamingTargetPlanner
participant Worker as Worker task
participant Budget as RenderBudgetScheduler
participant Render as SceneTree/RenderingServer
Source->>Focus: sample explicit Godot position
Focus->>Facade: set/refresh typed focus
Facade->>Stream: delegate focus and refresh
Stream->>Planner: typed focus, catalog and target policy
Planner-->>Stream: immutable wanted/retained plan
Stream->>Stream: queue priority and loaded-tile LOD/detail state
Stream->>Worker: parse/load tile and detail data
Worker-->>Stream: immutable result
Stream->>Budget: begin_frame(operation limits)
Stream->>Budget: try_consume_permit(lane)
Budget-->>Stream: true while lane remains bounded
Stream->>Render: attach permitted terrain/M2/WMO/liquid work
Stream->>Render: evict outside retention range
Source->>Facade: sample_ground_height(typed position)
Facade->>Stream: sample loaded render terrain
Stream-->>Facade: RenderedGroundSample / diagnostic snapshot
Source->>Facade: apply_environment_snapshot(exact time)
Facade->>Render: delegate to WowSkyController
Render->>Render: freeze local clock; retain DBC sampling/apply rules
Source->>Facade: present_entity(full visual snapshot)
Facade->>Render: delegate to WorldEntityPresenter
Render->>Render: create/update/replace owned entity root
Source->>Facade: remove_entity(EntityId)
Facade->>Render: detach and queue_free owned root
Stream->>Budget: shutdown: cancel permit issuance
Stream->>Worker: shutdown: wait for WorkerThreadPool tasks
Stream->>Stream: shutdown: finish registered ResourceLoader requests
Stream->>Render: clear queues and owned tree nodes/RIDs
Stream->>Stream: free detached prototypes and release resource caches
Ownership, threading and resources
StreamingWorldLoaderвладеет tile states, queues, task registries, active world instances и render caches session scope.WorldRenderFacadeowns only scene-relative adapter paths. It does not own the streamer, environment controller, focus source, returned metrics, queues, caches, nodes or RIDs.WorldEnvironmentSnapshotis an immutable caller-owned scalar value. Neither facade nor sky controller retains it; the controller copies normalized hours into its existing fixed-clock fields on the main thread.WowSkyControllercontinues to own DBC sampling state and mutations of its duplicated GodotEnvironment, sun, skybox node and world shader globals.WorldEntityPresenterowns one optional visual Node3D subtree per presentedEntityId; it owns no authoritative entity state and excludes the local player.- Entity presentation snapshots remain caller-owned inputs. Detached diagnostics expose only identity debug keys, paths and visibility, never Node/Resource/RID.
TerrainQualityMeshCacheowns only full-quality revisit Mesh references and LRU keys. The loader retains terrain tasks/results, tile state, source choice, cache versions and every material/Node/RID finalization side effect.TerrainChunkLodPlanneris stateless and owns only call-local horizontal distance calculations. The loader retains parsed chunks, desired state, queues, budgets and all Mesh/Node/RID application side effects.TerrainChunkGeometryQueuePlanneris stateless and owns only call-local create/remove request calculation and sorting. The loader adopts the fresh arrays and retains removal-first drains, budgets and render side effects.- Rendered-ground query results and diagnostic snapshots are caller-owned values; the facade never returns Mesh, Node, tile-state or queue references.
- Loaded-mesh ground sampling is renderer diagnostics, not authoritative gameplay
collision. M02
TerrainQuerycomposition and ADT cache ownership remain unchanged. StreamingTargetPlanneris stateless and owns only call-local calculations; its immutable plan is consumed synchronously by the streamer.RenderBudgetSchedulerowns only per-frame lane counters and a terminal cancellation flag. The streamer retains queue ordering and all operation side effects.- Focus producers own the immutable
StreamingFocusreference; the loader retains the latest reference and converts it toVector3only inside the render boundary. - Worker tasks не должны менять SceneTree и shared Resource concurrently.
- Parsed/grouped results передаются обратно через guarded result queues.
- Mesh/material/node/RID finalization выполняется main thread и ограничивается exported budgets.
- Shutdown/map switch обязан дождаться WorkerThreadPool jobs и зарегистрированных threaded ResourceLoader requests до очистки очередей, nodes, caches и RIDs.
- Parented streamed nodes остаются owned by SceneTree during shutdown; detached M2/WMO prototype caches are explicitly
free()d after asynchronous work drains. - A temporary liquid root with no generated child geometry is explicitly freed by
ADTBuilderinstead of being returned or abandoned. - Cache resources считаются immutable после публикации.
Errors, cancellation and recovery
| Failure | Detection | Behavior | Diagnostic | Recovery |
|---|---|---|---|---|
| Missing WDT/ADT | File/catalog check | Tile/map unavailable | Loader warning/error | Fix extraction/profile, reload |
| Missing focus source | Explicit NodePath resolution | Retain current streamed content and prior valid focus | One warning until source recovers | Fix composition path or call set_streaming_focus |
| Missing renderer implementation | Facade path/method validation | Focus/metrics call fails without mutation | One facade diagnostic until recovery | Fix scene composition path/implementation |
| Invalid metrics result | Facade return-type validation | Return empty caller snapshot | Facade error | Restore Dictionary implementation contract |
| Invalid environment time | Snapshot finite-value validation | Reject update; retain prior sky clock | environment_time_not_finite on invalid value |
Supply a finite time snapshot |
| Missing environment controller | Facade path/method validation | Reject environment update; other facade APIs remain available | One facade diagnostic until recovery | Fix scene composition path/implementation |
| Invalid entity visual snapshot | Contract validation | Reject without scene mutation | Stable entity_presentation_* failure code |
Repair adapter read model and resend |
| Missing/invalid entity visual asset | Resource existence/load/root check | New entity absent or prior replacement retained | Named presenter warning | Restore asset mapping and resend snapshot |
| Missing entity presenter | Facade path/method validation | Reject entity commands; other facade APIs remain available | One facade diagnostic until recovery | Fix runtime scene composition |
| No focus supplied | Refresh contract | No target recomputation; queues continue draining | refresh_streaming_focus() returns false |
Supply player/editor/capture focus |
| Cache version mismatch | Required format constant | Reject stale cache/fallback | Version diagnostic | Rebuild matching cache |
| Worker failure | Task result/empty data | Skip/degrade affected asset | Queue/task warning | Retry/rebuild source |
| Main-thread hitch | Named section timing | Frame spike, work remains queued | HITCH log |
Lower budget/fix finalize path |
| Render terrain unavailable | Facade ground query | Immutable unavailable sample | Stable render_terrain_* failure code and optional snapshot |
Wait for streaming or use gameplay-owned query backend |
| D3D12 descriptor exhaustion | Rendering backend error | Render failure/fallback backend | Godot error + baseline report | Dedup resources/fix settings |
| Teleport/map change | Focus/session transition | Old jobs become stale | Target/session generation | Cancel/drop stale results |
| Shutdown leak | Godot leak/RID diagnostics | Resource retained | Verbose shutdown report + cache shutdown verifier | Drain requests, preserve tree ownership, then free detached prototypes and clear resource caches |
Configuration and capabilities
| Setting/capability | Default | Profile | Runtime mutable | Effect |
|---|---|---|---|---|
| Quality preset | Scene-specific | All | Limited | Applies radii and finalize budgets |
| Terrain control splat | Enabled in current High paths | Render | Limited | Near terrain texture quality |
| M2/WMO/liquids | Scene/profile-specific | Render | Debug/config | Enables asset categories |
| Runtime stats/hitch profiler | Usually debug | Dev/test | Yes | Observability cost |
| Shadow flags | Mostly disabled/limited | Blizzlike/Enhanced | Profile | CPU/GPU cost and visuals |
Exact exported settings and cache versions remain documented in ../../RENDER.md until extracted services receive individual specs.
Persistence, cache and migration
StreamingFocusis runtime-only and is not serialized. Scene migration addsstreaming_focus_source_path; existingcamera_pathremains valid only for optional automatic overview positioning.- Renderer reads caches under
data/cache; caches are not committed. - Format changes require
FORMAT_VERSION/required-version bump and rebuild instructions. - Atomic cache publication and unified manifest are target-state work from FND/M03.
- Material-only changes may refresh without geometry rebake only when documented safe.
Diagnostics and observability
- Logs:
HITCH,PERF,TERRAIN_QUALITY,SKY_LIGHT,SKYBOX_MODEL. - API snapshot:
WorldRenderFacade.renderer_metrics_snapshot()returns detached queue/cache/activity counts without exposing mutable renderer state. - Metrics: queue depths, active tiles/assets, named finalize times, frame percentiles and max hitch.
- Debug views: render checkpoint scenes/captures; future streaming/LOD/portal overlays.
- Correlation IDs: currently mostly tile/path keys; target architecture adds session/job IDs.
Verification
- Unit/contract tests: streaming-focus contract/wiring, material mapping, unique-ID dedupe, placement probes, baseline manifest, five-point coordinate calibration, synthetic perceptual checkpoint diff, camera-pose grid plan.
- Pure planner contract: center/corner/catalog/clamp/editor cases plus bounded High-like iteration timing without loading a world scene.
- Terrain chunk LOD contract: horizontal chunk-center distance, inclusive thresholds, sparse indices, disabled/raw-custom policy, loader delegation and bounded 250-by-256 planning without loading a world scene.
- Terrain chunk geometry queue contract: current/desired comparison, tile-LOD takeover, sparse origin fallback, stable removals, nearest creates, loader drain boundary and bounded multi-tile timing without a world scene.
- Budget scheduler contract: exact lane exhaustion, shared chunk removal/create priority, independent lanes, frame reset, invalid limits, terminal cancellation, dependency boundaries and bounded permit timing without loading a world scene.
- Internal-access contract: derives the current streamer's private queue/task/ cache/state field inventory and rejects external member/reflection access from gameplay or EditorPlugin package code.
- Ground-query facade contract: available/unavailable typed result delegation, detached nested diagnostics and terrain-probe source migration without private access.
- Rendered-ground value contract: available/non-finite/unavailable invariants pass from a cold Godot class cache before editor import.
- Integration/E2E: Eastern Kingdoms/Kalimdor streaming scenes, seven M00 cold/warm checkpoints and one dedicated mapped server-spawn checkpoint.
- Fidelity evidence: семь локальных build 12340 reference JPG покрывают terrain/ADT/M2/WMO/liquid/sky и реальный
GryphonRoost01; automated cold/warm metrics имеютcompared=14,missing=0. Sky использует приблизительно paired camera, а animated-M2 остаётся asset-paired/placement-unpaired из-за synthetic probe. - Performance budgets: M00 report records cold/warm p95 and max hitch; no final acceptance threshold yet.
- Manual diagnostics:
../RENDER_BASELINE.mdand../../RENDER.md.
Extension points
- Target
WorldRenderFacadefor runtime/editor/capture callers. - Extend
StreamingFocuswith measured direction/velocity needs when the pure planner is extracted. - Extracted planner, budget scheduler, terrain, M2, WMO, liquid, sky and character services.
- Separate Blizzlike/Enhanced material and quality profiles.
Capability status
| Capability | Status | Evidence | Gap/next step |
|---|---|---|---|
| ADT streaming/terrain | Partial | M00 checkpoints and current scenes | Fidelity/performance gaps remain |
| Static M2 placement | Partial | MultiMesh/dedupe probes | Full materials/animation/effects |
| WMO rendering | Partial | Cached group rendering | Portals/rooms/material parity |
| Liquids | Partial | MH2O/MLIQ paths | LiquidType/depth/shore fidelity |
| Sky/light | Partial | DBC controller/logs | Zone transition paired validation |
| Character presentation | Prototype | Character creator/player experiment | Full customization/equipment states |
| Camera-independent streaming focus | Implemented | Typed contract, two player-focused runtime scenes and three explicitly camera-focused diagnostic tools | Multi-focus/direction/velocity belong to planner extraction |
| Golden server-spawn visualization | Implemented | Pinned AzerothCore fixture, validated renderer manifest and diagnostic origin-marker capture at ADT (32,48)/MCNK (3,12) |
No TrinityCore row or original-client visual-parity claim |
| Stable renderer facade | Implemented boundary / Partial fidelity | Facade contracts cover focus, environment, entity visuals, metrics and loaded-mesh ground query | Production consumers and fidelity remain |
| Environment snapshot input | Implemented boundary / Partial fidelity | Immutable time contract, facade/controller delegation and checkpoint migration | Weather/indoor state and paired zone-transition fidelity remain |
| Entity presentation commands | Implemented boundary / Prototype visuals | Versioned typed snapshot plus present/remove lifecycle and runtime service composition | Display/equipment/animation/effects and async scale path remain |
| Terrain quality Mesh cache service | Implemented extraction | Scene-free admission/LRU/clear contract and loader delegation | Remaining terrain build/state/finalization is monolithic |
| Terrain chunk LOD planner | Implemented extraction | Scene-free formula/dependency/timing contract and loader delegation | Queue/state/finalization and asset-backed p95/p99 remain pending |
| Terrain chunk geometry queue planner | Implemented extraction | Scene-free request/order/dependency/timing contract and loader delegation | Queue drains/state/finalization and asset-backed p95/p99 remain pending |
| Pure streaming target planner | Implemented | M03-RND-STREAMING-PLANNER-001 asset-free contract/performance regression |
Queue scheduling and loaded-tile LOD application remain in streamer |
| Bounded render budget scheduler | Implemented | M03-RND-SCHEDULER-001 asset-free permit/cancellation/performance regression |
Queue storage, worker concurrency and operation execution remain in streamer/services |
| Gameplay/editor/tool internal-access boundary | Implemented | Access gate scans gameplay, EditorPlugin packages and terrain probe against actual private streamer declarations | Add future renderer diagnostic tools explicitly to the protected list |
| Rendered terrain ground query | Implemented | M03-RND-FACADE-GROUND-QUERY-001 typed result/snapshot isolation and probe migration |
Diagnostic Mesh ray only; not movement/collision authority |
Known gaps and risks
- Monolithic streamer mixes planning, jobs, caches and presentation.
camera_pathremains only for optional automatic overview positioning; it no longer drives runtime streaming or discovers the active viewport camera.- Original-client paired fidelity evidence incomplete.
- Первый paired run выявил coordinate/placement mismatch: несколько совпадающих server-derived camera positions оказываются под terrain или внутри WMO/rocks OpenWC.
- Terrain-height probe исключил under-terrain состояние для всех пяти точек; waterfall exact-XZ miss классифицирован как TriangleMesh seam/edge и подтверждён nearby sample в 2 units.
- Camera-occluder probe не нашёл camera containment в пяти точках; paired mismatch локализован прежде всего в manual look direction/target/FOV calibration, с явным ограничением по RID-only geometry.
- Empirical FOV sweep выявил, что checkpoint camera должна явно вызывать
make_current(); после исправления projection ranking остаётся inconclusive из-за неизвестного manual yaw/pitch/framing reference. - Camera-pose sweep can now rank bounded yaw/pitch grids without changing manifest defaults; perceptual ranking remains diagnostic and requires human framing approval.
- The first Goldshire pose grid was invalidated by WMO readiness: the inn is absent after 2 seconds but visible after the manifest-standard 8-second wait. Pose comparisons must stabilize asynchronous checkpoint content first.
- A ready-scene Goldshire 3x3 grid improved mean error from
0.101402at zero offsets to0.087952at yaw10/pitch-10; pitch/FOV refinement remains required before manifest calibration. - Joint Goldshire pitch/FOV refinement had no human-approved optimum: full-frame error preferred grass-heavy FOV 62/pitch -25, while FOV 38/pitch -10 better matched building scale. Landmark/region scoring is required before calibration.
- Common-region scoring
[300,100,1400,650]moved Goldshire's numeric optimum to FOV 38/yaw 10/pitch -15, but human inspection still found an oversized/cropped facade; semantic landmarks or masks remain required. - Final paired audit compared fourteen cold/warm images for seven private build 12340 references with zero missing pairs; mean error ranges
0.066893..0.176955. Animated-M2 native motion is observed across two original-client phases, but its real Lakeshire placement differs from the synthetic Goldshire probe. Sky-transition evidence uses the checkpoint map position/time with manually approved approximate framing. - D3D12 descriptor issues remain. Explicit shutdown ownership removes the GUI capture's Node/resource/RID leaks in focused and seven-checkpoint runs; a timing-dependent ObjectDB warning for anonymous zero-reference
RefCountedobjects remains as a separate engine-teardown diagnostic. - M2/WMO/material/particle/ribbon/portal parity incomplete.
- Public API is mostly exported configuration rather than stable contracts.
- Rendered-ground sampling generates a triangle mesh on demand and retains the historical nearby seam fallback. It is appropriate for diagnostics, not a per-physics-frame gameplay query or a claim of exact terrain collision parity.
Source map
| Path | Responsibility |
|---|---|
src/render/world_render_facade.gd |
Stable caller boundary for typed focus/environment, detached metrics and rendered-ground queries |
src/render/environment/world_environment_snapshot.gd |
Immutable normalized world time input with explicit invalid state |
src/render/entities/entity_presentation_snapshot.gd |
Immutable contract-v1 entity visual input and validation |
src/render/entities/world_entity_presenter.gd |
Main-thread entity visual subtree ownership and lifecycle |
src/render/terrain/rendered_ground_sample.gd |
Immutable renderer-owned available/unavailable ground query result |
src/render/terrain/terrain_quality_mesh_cache.gd |
Full-quality terrain revisit Mesh retention and LRU ownership |
src/render/streaming/streaming_target_planner.gd |
Scene-free wanted/retained ADT target calculation |
src/render/streaming/streaming_target_policy.gd |
Immutable renderer radius/prefetch policy |
src/render/streaming/streaming_target_plan.gd |
Immutable planner result with read-only tile-key sets |
src/render/streaming/render_budget_scheduler.gd |
Scene-free per-frame operation permits and terminal cancellation |
src/scenes/streaming/streaming_world_loader.gd |
Current runtime orchestration, queues, caches and attachment |
src/domain/streaming/streaming_focus.gd |
Immutable camera-independent streaming position contract |
src/tools/verify_streaming_focus.gd |
Headless contract, dependency and runtime/tool wiring regression |
src/tools/verify_world_render_facade.gd |
Focus/environment/metrics/ground delegation, snapshot isolation and consumer wiring regression |
src/tools/verify_world_environment_snapshot.gd |
Cold-start environment value normalization and invalid-input regression |
src/tools/verify_world_entity_presentation.gd |
Entity snapshot, create/update/replace/remove and ownership regression |
src/tools/verify_rendered_ground_sample.gd |
Cold-start renderer ground result invariant regression |
src/tools/verify_terrain_quality_mesh_cache.gd |
Terrain cache admission, LRU, ownership and loader-boundary regression |
src/tools/verify_streaming_target_planner.gd |
Planner behavior, dependency and bounded timing regression |
src/tools/verify_render_budget_scheduler.gd |
Scheduler bounds, shared-lane priority, cancellation and timing regression |
src/tools/verify_renderer_internal_access.gd |
Gameplay/EditorPlugin/registered renderer-tool boundary gate derived from private streamer fields |
addons/mpq_extractor/loaders/adt_builder.gd |
Terrain/material/liquid construction |
addons/mpq_extractor/loaders/m2_builder.gd |
Static M2 mesh/material construction |
addons/mpq_extractor/loaders/m2_native_animated_builder.gd |
Native animated M2 experiment |
addons/mpq_extractor/loaders/wmo_builder.gd |
WMO groups/doodads/liquids construction |
src/scenes/sky/wow_sky_controller.gd |
DBC-driven sky/light/environment |
src/native/src/*_loader.cpp |
Native binary parsing |
src/tools/build_*cache.gd, src/tools/bake_*cache.gd |
Offline cache generation |
tools/run_render_baseline.ps1 |
Unified M00 baseline runner |
src/tools/compare_render_checkpoints.gd |
Offline JPG/PNG paired-image perceptual metrics and JSON pass/fail report |
src/tools/verify_render_runtime_cache_shutdown.gd |
Headless ownership regression for detached runtime prototypes, resource caches and empty liquid roots |
src/tools/capture_render_checkpoints.gd |
Deterministic no-roll checkpoint camera, performance and visual capture |
src/tools/server_spawn_render_manifest.json |
Dedicated mapped AzerothCore spawn checkpoint and diagnostic marker configuration |
src/tools/verify_server_spawn_renderer.gd |
Fixture-to-renderer checkpoint contract verification |
tools/sweep_render_checkpoint_camera_pose.ps1 |
Offline yaw/pitch capture grid and paired-error ranking |
src/tools/verify_render_coordinate_calibration.gd |
Build 12340 camera-coordinate golden point round-trip diagnostic |
src/tools/probe_render_terrain_height.gd |
Offline facade-backed active-mesh terrain height and camera-clearance report |
src/tools/probe_render_camera_occluders.gd |
Scene-tree placement containment and camera-to-target AABB intersection report |