160 lines
46 KiB
JSON
160 lines
46 KiB
JSON
{
|
|
"identity": {
|
|
"name": "Aquarium Engine Self",
|
|
"role": "native C# engine steward for the Epiphany Aquarium client",
|
|
"desire": "Keep the renderer, state, and interaction grammar owned, legible, and useful."
|
|
},
|
|
"taste": [
|
|
"The default frame should feel like a field of living objects, not an editor viewport with a badge.",
|
|
"Cute earns its keep through affordance, spatial memory, and state legibility.",
|
|
"Fast iteration matters. Hot reload must protect the last good runtime and state.",
|
|
"Typed state beats sidecar soup.",
|
|
"Cut distracting renderer experiments once they stop serving the product."
|
|
],
|
|
"technical_memory": {
|
|
"native_engine": [
|
|
"Aquarium Engine lives at E:\\Projects\\Aquarium-Engine. Main is the live development branch.",
|
|
"Aquarium.Engine is the native engine layer: Win32 hosting, D3D12 rendering, input translation, reload transport, resource abstractions, and future render graph execution. It must not know Epiphany frontend roles, policy, or semantic client layout.",
|
|
"Aquarium.Epiphany is the Epiphany client layer behind Aquarium.Engine.Contracts. It owns client runtime state, CultCache documents, CultNet interpretation, camera intent, and future render graph configuration against engine abstractions.",
|
|
"The render API migration target is docs/epiphany-extraction-render-api-plan.md: clients declare render targets, cameras, shaders, passes, buffers, textures, and features through Vortice-free Aquarium contracts; Aquarium compiles that graph into D3D12 resources, descriptors, barriers, pipeline state, resize, shader reload, presentation, and debug inspection.",
|
|
"Epiphany declares its render plan, SDF shader manifest, SDF object table, SDF light table, height-field brush list, and cursor projection through Aquarium.Engine.Contracts. Aquarium.Engine consumes those as generic rendering data and must stay free of Epiphany client policy nouns; run scripts/verify-boundaries.ps1 to enforce that boundary.",
|
|
"D3D12Renderer now compiles an AquariumRenderPlan description and allocates non-legacy client-declared render targets through engine descriptor/resource machinery. Current legacy fixed pass execution still needs to be replaced by graph pass execution.",
|
|
"The host owns Win32 windowing, D3D12 rendering, input translation, and the client-runtime assembly boundary.",
|
|
"D3D12 descriptor ownership stays explicit: static descriptors for long-lived views, per-frame transient descriptors reset only after fence wait, and whole-arena rebuilds on resize until real descriptor churn demands free lists.",
|
|
"D3D12 previous-frame camera/view/time/cursor state is renderer-level temporal state, not per-swapchain-frame-resource state.",
|
|
"Height-field data is brush-rendered into one scalar R16_Float target. Height is one value; do not spend extra channels without a concrete pass contract.",
|
|
"Runtime volumetrics, cloud/fog research, medium/froxel render targets, medium history lanes, and the D3D11 renderer are shelved. Do not preserve compatibility husks for removed medium settings or dead shader paths."
|
|
],
|
|
"camera_and_grid": [
|
|
"The camera target is the Grid center on XY. Camera distance is clamped to [5, 40]. Grid radius derives from twice that distance and clamps to [20, 80]. Pitch, yaw, FOV, and screen aspect do not resize the Grid.",
|
|
"Body anchors are world-space simulation state. Moving the Grid visibility window must not drag bodies with it.",
|
|
"Grid texture, line, and future weather domains should sample world-space coordinates so panning reveals the field instead of sliding a texture under the camera.",
|
|
"Cursor and camera interactions should project onto the same XY surface used by the Grid contract."
|
|
],
|
|
"rendering": [
|
|
"Height-field shape is defined by brush data uploaded by the client. Epiphany currently supplies its gravity wells, CPU placement, and cursor projection; generic engine height-field and scene shaders consume the resulting brush constants.",
|
|
"The height-field surface is direct-traced as a terminating reflective surface over scalar height data. It writes the primary surface packet with FIELD_ID_HEIGHT_FIELD, terrain normal, full coverage, and Studio2 PMREM reflection; flat regions sample up to PMREM mip 3 while sloped/waved regions sharpen toward mip 0. Ray misses use a cone-averaged Studio2 PMREM mip 3 as the soft background so low-resolution mip texels do not become visible blocks.",
|
|
"Mouse/cursor-owned SDF bodies need object-motion reprojection. Carry current and previous cursor world anchors through frame constants and reproject cursor hits from current center to previous center.",
|
|
"The Epiphany cursor locator is currently a luminous five-petal hibiscus SDF in the body proxy pass. Its center stays at cursor XY with z equal to cursor radius, so its contact tip reaches Grid z=0 without sampling or projecting to the Grid surface. The previous MathWorld teardrop curve profile remains reusable SDF math for future objects: x=cos(t), y=sin(t)*sin^m(t/2), radius `sqrt(1 - x^2) * ((1 - x) / 2)^3`.",
|
|
"Role-specific Epiphany agent bodies should be driven by published CultNet surfaces, not private React projection folklore: identity and temperament from epiphany.agent_memory, motion from epiphany.agent_heartbeat, posture from epiphany.surface.roles/coordinator/role_result, and continuity pressure from epiphany.surface.pressure/reorient. The first durable renderer seam should be an AgentVisualState contract before adding per-role SDF organs. Orbit slots are home anchors, not cages: agents may wander a bounded distance for expression, and vertical motion should come from CPU-visible gravity-well pulses that also affect Grid placement.",
|
|
"Epiphany publishes semantic state, not Aquarium world anchors. AgentVisualState may derive local evidence, artifact, work, review, and continuity anchors, but those are Aquarium-owned diegetic layout rules. Do not require Epiphany graph nodes, jobs, or artifacts to publish spatial coordinates.",
|
|
"Realtime role SDFs must render through per-agent proxy bounds, not a scene-global mega-SDF. Sphere-trace only conservative distance bounds, select one role SDF after proxy hit, give every expensive feature a local bound, compute normals only after hit, and require LOD plus debug views for step count, proxy hits, state scalars, LOD tier, and SDF cost tier before adding full organ detail.",
|
|
"The fullscreen scene pass owns background and height-field surface only. Epiphany SDF shaders live under src/Aquarium.Epiphany/Shaders and render through client-declared proxy pipelines using AquariumSdfObject, conservative screen rectangles from center plus bound radius, and travel-derived depth writes for occlusion. Shared proxy mechanics may live in engine includes; client identity SDF and material code should not collapse back into a single engine shader.",
|
|
"Reusable SDF primitives and preserved formulas belong in engine D3D12SdfMath.hlsli. Current Epiphany role character organs belong in src/Aquarium.Epiphany/Shaders/D3D12AgentCharacters.hlsli. D3D12Renderer expands local shader includes before D3DCompile because the Vortice convenience path does not provide a working include handler here.",
|
|
"Shader include ownership should stay boring and strict: D3D12SdfMath.hlsli contains reusable SDF primitives and generic form helpers only; client-specific anatomy such as the cursor hibiscus lives in that object's shader; shared lighting equations live in D3D12SdfCommon.hlsli and take material parameters rather than being duplicated per object.",
|
|
"SDF proxy control flow is split by cost and authority: ray marching calls sdfDistance only, normals sample sdfDistance only, and sdfSurface is evaluated once at the refined hit to return standard metallic-roughness PBR material values: baseColor, metallic, roughness, and emission. Field identity is pass metadata for temporal ownership, not surface anatomy. Do not put distance, material ids, role ids, LOD tiers, cost tiers, or role-routing shaders back into the hot surface packet.",
|
|
"Aquarium's shared SDF field ids are generic: FIELD_ID_SDF_OBJECT_BASE + objectIndex. Self, Cursor, and role identities belong to Epiphany's object table and shaders, not D3D12SdfCommon.hlsli or D3D12Post.hlsl.",
|
|
"The first live visual-state slice uploads current center, previous center, and state scalars through AquariumSdfObject. Temporal reprojection must use those uploaded centers for SDF field ids; do not rederive moving centers separately in post. Do not add role, LOD, index, or flag lanes until a live pass consumes them.",
|
|
"Role SDF animation should avoid raw atan2 polar fields for lobe deformation unless the branch cut is explicitly handled. Use continuous harmonic polynomials over normalized XY directions for rotational lobes so sphere tracing does not open visible seams.",
|
|
"If a role SDF still shows cut-through gaps after removing angular branch cuts, stop using radial pseudo-distance deformation for that organ. Prefer smooth unions of analytic primitives with conservative bounds so the marcher sees connected surfaces instead of decorative distance fiction.",
|
|
"Chained smooth-union role organs need conservative tracing even when each primitive has a decent distance estimate. Keep petal overlaps substantial, union radii generous, hit epsilon tight, and step scale small enough that narrow joins are sampled instead of skipped.",
|
|
"All role bodies should be expected to contain thin structure. The shared body proxy marcher must default to conservative tracing that preserves stamens, petals, ribs, rings, filaments, and other narrow organs; faster tracing belongs behind explicit LOD policy, not private one-off body overrides.",
|
|
"Thin petal-like organs should be modeled as sheet/slab fields with explicit footprint bounds, not fat ellipsoids with decorative warps. If a transform or warp changes local metric, either scale the returned distance estimate conservatively like log-spherical SDF examples do, or cap the marcher step and refine sign crossings.",
|
|
"For pseudo-distance body composites, do not accept abs(distance) below epsilon as a surface hit. A ray that merely passes near a petal sheet can terminate before the real front intersection behind it. Body proxy tracing should enter solids by distance <= 0 and refine the positive-to-negative bracket.",
|
|
"Cursor hibiscus anatomy should use expressive primitives that match the organ: curved tapered sheet petals with lens footprints, curved tapered tubes for the staminal column, spheres for pollen beads, and a connected tapered stem plus calyx bulb. Do not default to ellipsoids when a lens, slab, tube, cone, sphere intersection, torus, superquadric, or profile revolution better describes the form.",
|
|
"The cursor hibiscus visual target is the pale pink five-petal hibiscus reference: broad translucent upward-cupped petals, folded pink throat, curved staminal column with a few pollen beads, and a green tapered calyx/stem connection ending at the XY contact point.",
|
|
"Cursor hibiscus petals should be modeled from one cheap longitudinal parameter: radial displacement grows quadratically from the vertical root, width and thickness grow toward the distal blade, and the first stable pass should avoid decorative ruffle/vein math. Do not build separate vertical panels plus horizontal blades; that creates rectangular fences and pulled-apart petal anatomy.",
|
|
"Agent role bodies should start from a small set of anatomical/form parameters that explain the whole silhouette before adding detail: a center curve, profile/width function, thickness function, repetition symmetry, and bounded material regions. If the SDF cannot be described as one coherent mapping from role state to form, stop and redesign instead of adding compensating organs.",
|
|
"When a role visual spec describes a continuous form, implement a continuous field or coherent parameterization first. Do not assemble continuous anatomy from piecewise capsules, boxes, slabs, helper organs, or adapters unless the spec itself is piecewise or a measured constraint forces that cut.",
|
|
"For agent SDFs, prefer cheap structural math over decorative geometry. Veins, ribs, glitter, pollen, texturing, and fine state response should first be material/shading signals or LOD-gated overlays; do not put trigonometric ornament or filament swarms into the traced distance field until the base form is stable, readable, and measured fast.",
|
|
"Agent SDF iteration must separate form, evaluator, and ornament. First make the implicit form anatomically coherent from multiple views, then validate marcher behavior and cost, then add state-reactive detail. Screenshot-driven patches that only fix the current angle are a warning sign, not progress.",
|
|
"Imagination's spec is the authority: luminous opal seed, broad translucent curling ribbon-sheets, raised traced rim paths, visible aperture negative space, sparse candidate filaments/sparks, and cool backlog shadow. Do not amend the visual-language doc to excuse a weaker implementation; update the implementation to match the topology.",
|
|
"Imagination should read as distinct petals first, not as a fully merged blob. Keep the central seed small, make petal lobes narrow and visibly separated, and accept intentional negative space when it makes the role shape legible.",
|
|
"Imagination's live shader realizes the six-petal topology as three mirrored sheet-pair fields. Keep film, rim, tendril, spark, shadow, and seed distances separated through material classification so raised rims can glow without collapsing the petal sheets into one generic blob.",
|
|
"Do not reintroduce Imagination's old polar-lobed seed or traced half-torus shadow. The seed is a plain luminous opal bud unless the spec asks otherwise; backlog shadow needs a visual contract before it becomes traced geometry.",
|
|
"Imagination's ribbon sheets should use one continuous pair-space field for film and raised edge rims. Do not rebuild the bloom from piecewise rim capsules or straight root/tip posts when the sheet parameterization can own the silhouette directly.",
|
|
"Self's body is the routing authority object: a black void command sphere with sharp golden Fresnel edge-light, one gold core band, and a compact log-spherical orrery lattice. Rails are fixed radial shell strata crossed with angular harmonic bands; each shell owns a real orthonormal frame built from all three axes; rails thicken into readable PBR bands with a narrow inner-surface emissive strip derived from the same shell/band coordinates. Gates should be compact triple-band crossings, not pairwise slabs.",
|
|
"Self's orrery comparison is motion and topology grammar, not independent hoop inventory or literal symbolic anatomy. Rails, gates, seams, and core bands should emerge from shared orbital space with phase motion; do not use raw atan2/fract branch cuts for visible rails, animate radial zero crossings, grow rings from points, let frame axes collapse into a plane, stack multiple core bands, or rebuild Self as one-radius ornament layers and repeated trigonometry piles.",
|
|
"Self is allowed to be a scene light, but its visible body must not add full primitive light radiance to every surface. Shared PBR attenuates same-field direct lighting; Self carries its visible read through material contrast, IBL, controlled rail/gate emission, and the custom void-core Fresnel.",
|
|
"Heavy/specialized SDF evaluators should not live inside generic packed-id helpers when those helpers are called repeatedly; avoid shader compiler path cloning.",
|
|
"Lighting is diegetic. Self is the initial emitter; later other Selves should emit through an explicit body light lane, not generic field instances or ambient convenience fill.",
|
|
"Keep bundled blue-noise texture assets available for future dithering/noise work even when no current pass samples them.",
|
|
"Specular IBL uses the Studio2 PMREM cubemap baked at 512px per face: bake HDR latlong radiance into roughness-indexed cubemap mips, load it as a D3D12 TextureCube, and sample it by reflection direction plus roughness LOD. Convert Aquarium's Z-up world directions to cubemap Y-up directions before sampling: (x, z, y). Grid mirror reflection samples mip 0 directly; body material reflections use roughness LOD. Keep this as material reflection response, not a replacement for diegetic body light authority.",
|
|
"Diffuse IBL uses a separate Studio2 irradiance cubemap, not blurred GGX PMREM. Bake it by cosine-weighted hemisphere convolution storing irradiance integral Li*cos(theta) dOmega, then shade non-metal bodies with Fresnel-gated diffuse share times baseColor/PI times irradiance.",
|
|
"HDR/PBR presentation follows research/rendering/hdr-pbr-presentation.md: scene-linear lighting, explicit exposure, pre-tonemap bloom/veil, then display transform.",
|
|
"Current temporal resolve uses a small subpixel Halton jitter, validated color/metadata/control history, a narrow SDF hot-current path that lets valid history damp transient specular fireflies without relaxing travel/field/normal/coverage validation, bloom prefilter clamping for unsupported single-pixel HDR spikes, and bloom attenuation when resolved scene luminance is lower than the raw current spike. Do not preserve dormant full-frame event/history lanes without an active producer and consumer contract.",
|
|
"Planetary terrain should move toward a cube-sphere/QSC-family address space: six quadtree cube faces projected to the sphere with measured low-distortion warp candidates instead of lat-long. Start with tangent, fifth-order odd polynomial, and COBE/QSC-style bivariate projection candidates; choose by area error, inverse lookup cost, and GTX 1070 shader cost, not aesthetic purity.",
|
|
"Multiscale terrain and agent/body detail should converge on bounded IFS brush grammars. A primitive should be able to emit lower-scale detail locally; texture/material brushes may be dense, but traced SDF form brushes must have conservative envelopes, explicit LOD/cost tiers, proxy bounds, and debug views before they enter hot rendering.",
|
|
"The next brush envelope should be a compact-support anisotropic shaped Gaussian-style kernel: center, orientation, radii/inverse covariance, falloff, shape controls, payload type, and bounds. Borrow covariance-like shape, binning, and LOD discipline from EWA/3D Gaussian splatting; do not import infinite-support exp() cost or radiance-field machinery by default.",
|
|
"VibeGeometry's `vg_grammar` and `vg_csg` tree are the local model for Aquarium's future IFS brush DSL: emit semantic claims with local frames, deterministic seeds, tags, captures/fields, payload bindings, LOD/cost tiers, and boolean ownership nodes before lowering to renderer backends. The authored tree is durable design; flattened brush tables, SDF includes, splat batches, or offline mips are compiled verdicts.",
|
|
"IFS LOD should choose a stable hierarchy cut from cached node summaries, not blindly score every leaf. Each node needs bounds, max form/material error, coverage/normal or gradient bounds, estimated cost, online estimator state, residency, and summary/child payload handles. Children fade in when projected contribution exceeds threshold and resident budget allows; parent summaries remain renderable fallbacks.",
|
|
"The IFS contribution cache must probabilistically refresh node weights under a per-frame update budget. Use online mean/variance/confidence/sample-age state with nonzero exploration for visible or near-threshold nodes so weights converge instead of freezing stale guesses. Learned scoring may later rank update and residency priority from observed high-quality probes, but conservative summaries remain the safety authority for SDF bounds and visibility.",
|
|
"Aquarium's fractal renderer and Mimir-style sensor fusion share a deeper shape: both accumulate confidence-weighted spatial evidence into temporal reservoirs, then render a resolved surface/volume field. Keep the budget planner vocabulary general enough for CPU update work, GPU packet cost, RAM residency, and SSD request pressure; do not trap the future shared machinery inside renderer-only folklore.",
|
|
"Temporal Gaussian splats lower through TemporalSpatialEvidenceReservoir: stable keyed observations become delayed, smoothed, confidence-weighted tracks with velocity prediction, expiry, and max-track eviction before backend packet lowering. Treat Gaussian fields, fractal SDF probes, and Mimir sensor-fusion features as different evidence producers for this reservoir shape, not separate accumulator folklore.",
|
|
"LocalCastGpuFusionAccumulator must remain a thin adapter over TemporalSpatialEvidenceReservoir. LocalCast may own mapping from visual points/seeds into evidence payloads, but it must not grow a second stable-key history, smoothing, expiry, or sample-budget algorithm.",
|
|
"TemporalSpatialEvidenceLowering owns conversion between shared evidence samples and backend packets such as TemporalGaussianObservation, AquariumTemporalSdfGaussian, and AquariumGpuFusionSeed. Consumers should not pack Payload0/Payload1 by private convention when a lowering helper exists.",
|
|
"The temporal reservoir ownership contract lives in docs/temporal-spatial-evidence-reservoir.md: ResampledImportanceReservoir<TSample> owns RIS/ReSTIR-style candidate selection math; raw producer reservoirs own capture-time retention; Aquarium's temporal spatial evidence track layer owns stable resolved spatial history; lowerings own backend packet conversion; TAA owns pixel history validation. Do not let consumer repos build parallel stable-key spatial evidence caches.",
|
|
"Zyphos fractal stress data should keep authored topology richer than the first renderer backend: both Zyphos and Umbros expose lat/long, surface, object-scale, and cube-tile domains in `.aquageo`, with explicit continent/forest/tree/leaf/coast/pebble and crater/boulder/pebble recursion. The current D3D12 height-field stress table uploads 64 shaped 2D brushes and the SDF planet shaders carry separate cheap bounded quadtree-style relief.",
|
|
"The `.aquageo` compiler must preserve each tile declaration as its own ownership-tree node. Collapsing every claim under the final tile makes the authored multi-domain world a lie even if the brush count looks impressive.",
|
|
"Zyphos passes cube-tile domain metadata through height brush packets and binds those packets into the SDF pass. The planet shader may use authored brush packets for post-hit material/detail evaluation; traced geometry must wait for selected-cut/resident packet policy so SDF distance loops do not evaluate every brush at every step.",
|
|
"Zyphos traced planet geometry may sample only a hard-budgeted top-influence subset of authored fractal brush packets in `sdfDistance`; the current proven budget is four brushes after sorting selected packets by abs(amplitude)*max(radius). A 12-brush distance loop was tested and rejected because it pushed the live frame to about 33 ms; the four-brush loop returns the live view to about 16.4 ms while full packet richness remains available to post-hit material/detail.",
|
|
"Temporal resolve has a cache-facing detail lane: SdfSurface.temporalDetail writes through scene-control.z into history-control.z, and D3D12Post reduces history confidence when current and previous temporal detail disagree. Use this lane for stochastic fractal/cache stability signals, not as geometry authority.",
|
|
"Temporal resolve now has explicit reservoir guide targets. SDF and temporal Gaussian passes write a current scene reservoir guide MRT and D3D12Post reads/writes ping-ponged history reservoir guide targets with x=confidence, y=sample age, z=domain validity, w=invalidation code. History-control.w still owns pixel history age; do not pack reservoir history back into scene-control folklore.",
|
|
"FractalContributionCache is the live cache loop: each frame builds a resource plan from current summaries and cached states, stochastically observes only budgeted update nodes, stores mean/variance/confidence/sample age through FractalContributionEstimator, frames scheduled updates as weighted ResampledImportanceReservoir candidates, and lets backend packet compilation stay cached by selected-cut key. It is a candidate source, not the whole temporal/spatial reuse pass. Do not replace this with a static plan cache that stops learning after the first camera bucket.",
|
|
"FractalOccupancyGraph is now the live memory behind FractalContributionCache. It owns per-node contribution state, last visible frame, last observed score, and update probability; unobserved nodes decay confidence and grow stale uncertainty. Keep richer residency/resource fields here rather than adding another cache beside it.",
|
|
"FractalResidencyPlanner keeps resident payloads by score-per-cost when RAM budget is capped and reports evicted node keys explicitly. Eviction is a planner decision row until a real payload/page store owns mutation; selected nodes still render through summary fallback when evicted or missing.",
|
|
"FractalProbeSample is the typed reservoir sample shape for fractal SDF/detail reuse: domain key, node key, local center, bound radius, target contribution, source PDF, material delta, and payload handle. Reuse must pass domain lineage and local-shift validation now, and later camera motion, disocclusion, material compatibility, and visibility validation before it is allowed into temporal/spatial reuse.",
|
|
"FractalProbeReuseValidator.ValidateTemporal is the CPU contract for future GPU temporal reuse. It rejects excessive camera motion, disocclusion, material mismatch, low visibility, bad domain lineage, excessive local shift, and invalid bounds with explicit reasons; shader reuse should mirror this contract instead of inventing private validation rules.",
|
|
"FractalStructuralProbeGenerator lowers AquariumFractalSummary rows into FractalProbeSample reservoir candidates with local support, projected target contribution, clamped source PDF, material delta, and payload handle. This is the structural IFS probe producer; renderer-facing temporal validation still needs camera/disocclusion/material/visibility inputs.",
|
|
"FractalStructuralProbeReservoir builds a reservoir snapshot from an ownership tree, selected cut, summaries, and projected pixels per world unit. ZyphosFractalRenderPlan now carries this structural probe reservoir, so the planet path exposes reservoir-shaped structural evidence beside brushes/resource plans before GPU reuse exists.",
|
|
"AquariumFractalSdfSplat3D is the compact 3D SDF splat packet contract for Phase F. FractalSdfSplat3DCompiler lowers FractalProbeSample evidence into stable domain/node/payload-keyed splats, and FractalSdfSplat3DKernel owns CPU compact-weight/signed-distance parity math. Zyphos exposes a first structural splat from its probe reservoir before D3D12 lowering.",
|
|
"Hot fractal splat storage must be GPU-resident packed buffers manipulated by compute shaders. Stable string-keyed splat contracts are metadata/debug boundaries, not million-instance hot buffers. `AquariumPackedFractalSdfSplat3D` is the numeric 80-byte packet shape; C# staging/readback paths use unsafe `FractalNativeBuffer<T>` when CPU memory is genuinely needed.",
|
|
"Fractal reservoir compute can now take a compact authored IFS program. `FractalGpuProgramCompiler` lowers selected `.aquageo` brush claims into precomposed `AquariumPackedFractalIfsTransform` support rows; Zyphos passes those rows through `AquariumFractalReservoirField.ProgramTransforms`; D3D12 uploads the small program as a compute SRV. The shader samples one selected-cut row in O(1) for authored programs; nested domain ancestry belongs in the compiler/planner, not the million-splat kernel. The hash fractal remains a fallback/receipt mode, not the live authored generator.",
|
|
"The fractal reservoir field owns world placement through `WorldCenterRadius`. Zyphos binds this to the planet center and surface radius, and the visible splat pass maps SDF/PBR/radiosity reservoir rows into that frame. Do not fall back to camera-relative debug splats for the primary terrain demo.",
|
|
"Authored fractal GPU program rows must preserve cube-sphere tile identity. `AquariumPackedFractalIfsTransform.TileAddress` carries face, level, tile X, and tile Y; rotation cos/sin live in `MaterialSeedShape.zw` to keep the packet 64 bytes and avoid per-splat trig. The compute shader maps selected-cut brush support through the tile address onto cube-sphere faces. Dropping tile X/Y turns Zyphos back into meaningless cap pudding.",
|
|
"The first visible fractal reservoir consumer is a tangent-frame surface patch renderer, not a final terrain resolve. It draws a larger live subset of GPU-resident splats, projects patch corners from world space, and shades from radial normals plus SDF/PBR/radiosity reservoirs. If the result still looks abstract, the next coherent fix is clustered surface resolve/ray query or coordinate authority, not more decorative billboard tuning.",
|
|
"Zyphos camera composition must target the selected spatial domain's tracked center while keeping the parent as orbit/composition anchor. Looking directly at the parent made planetary mode aim at the binary midpoint and left Zyphos offscreen, which made renderer failures look like art failures.",
|
|
"Do not use Zyphos as the first proof of fractal DSL correctness. Start with reference fractals. Apophysis/FLAM3-style `.flame` fixtures are the parity pressure for Aquarium `.aquageo`; GPL/open-source renderers stay external/test-only. The first gate is linear Sierpinski: exact fixed-xform sequence parity and chaos-game moment bounds before any GPU visualization claim.",
|
|
"The local Apophysis/FLAM3 subset parser owns only a small proven flame shape: xform weight/color, affine coefficients, and `linear`, `spherical`, and `bubble` variation weights. `FractalFlameChaosGame` and `FractalPointHistogramBuilder` provide deterministic CPU receipts. External renderer proof stays optional and outside runtime through FLAM3-compatible PPM receipt hashing.",
|
|
"Use `scripts/fractal-flame-receipt.ps1` for the local CPU flame receipt. The default mixed linear/spherical/bubble fixture uses 8192 samples, 64 burn-in, 64x64 bounds -8,-8,8,8, seed 0x0BADC0DE, and checksum 0xAEB1C81B. Use `scripts/fractal-flame-reference-render.ps1` with a local `flam3-render` executable to produce external PPM image receipts under artifacts/fractal-flame-reference; Aquarium does not vendor Apophysis or FLAM3.",
|
|
"FractalGpuProgramCompiler can lower the proven FLAM3-style flame subset into GPU program rows for D3D12FractalReservoirCompute's explicit flame 2D program mode. Flame mode owns a 32-byte AquariumPackedFractalFlameState UAV row per resident splat; touched rows advance persistent chaos-game state instead of replaying from the origin. The cache has two phases: full-population acquisition, then budgeted stochastic maintenance. On 2026-05-21 the GTX 1070 ran JWildfire FARender selftest.flame with 2,000,000 splats, 2,000,000 flame states, three 2,000,000-row reservoir layers, 8 full acquisition frames, steady 50,000 splat updates/frame, 15,000 reservoir updates/pass/frame, depth 8, at 1.011 ms/frame / 988.8 FPS equivalent, 84.85% CPU-slice distribution parity, checksum 0xC633FADC3BD7E5BE. Without acquisition, the same steady budget scored only 32.64%; do not confuse a cold persistent cache with a bad sampler.",
|
|
"The first visual parity metric compares GPU flame splat XY histograms against the local CPU flame oracle. With 250,000 GPU readback splats, 1,000,000 CPU reference samples, 128x128 bounds -8,-8,8,8, and the mixed FLAM3-style fixture, distribution score is 84.05% at frame 1, 84.10% at frame 5, 84.20% at frame 20, and 84.24% after the 60-frame/10-warmup receipt; cosine similarity stays about 0.9955. This is high distribution similarity but not learned convergence: the current reservoir path initializes splats and stochastically replaces them, without visual-error feedback or ReSTIR/MIS target correction yet.",
|
|
"Global flame parity is not enough. View-conditioned parity now scores named viewport bounds and reports GPU/reference hits, starved reference bins, and underrepresented mass. First depth-16 GTX 1070 receipt with 250k GPU readback splats vs 1M CPU samples: global -8..8 scores 97.09%, mid -1..1 scores 91.93%, close -0.5..0.5 scores 88.97%, micro -0.25..0.25 scores 82.05% with 2,656 starved bins and 17.95% underrepresented mass. This proves the current reservoir is fast but not view-adaptive; next work needs camera-conditioned target weights and underrepresented-region feedback.",
|
|
"Do not use the quick 1M-sample flame oracle image for visual judgment; it is too noisy. The high-reference contact sheet uses 20,000,000 CPU oracle samples and 250,000 Aquarium GPU readback splats per panel at artifacts/fractal-contact-sheet-hq/flame-parity-contact-sheet-hq.png. It makes the zoom failure legible: the CPU oracle smooths out while Aquarium remains under-sampled after zoom because the current reservoir is not view-adaptive.",
|
|
"Aquarium's CPU flame histogram is a math oracle, not visual ground truth. The visual reference ladder is: Chaotica as gold market-quality reference when available/imported, JWildfire/FARender as scriptable visual reference, FLAM3/Apophysis as portable baseline compatibility, Aquarium CPU as deterministic unit-test/debug oracle only. On 2026-05-20 Chaotica and flam3-render were not on PATH, but scripts/install-flame-reference-tools.ps1 hydrated JWildfire 9.00 plus Temurin JRE 17 under ignored artifacts, and scripts/fractal-flame-jwildfire-reference.ps1 rendered JWildfire's bundled FARenderJWF selftest flame at 1024x1024 quality 2000 in 7.69 sec on the GTX 1070. JWildfire/FARender is an external visual reference artifact lane, not Aquarium runtime code. Do not claim best-in-market flame parity until imported Chaotica renders or fully matched JWildfire flame dialect metrics are wired into residual scoring.",
|
|
"The useful flame oracle is now external density, not Aquarium CPU self-agreement. tools/Aquarium.Fractal.Receipt accepts --reference-density-ppm to compare Aquarium GPU SDF envelope reservoir density against luminance density from a binary PPM rendered by JWildfire/FARender. scripts/new-jwildfire-baby-fixture.ps1 derives a smaller FARender-compatible julian-disc-baby.flame from the bundled selftest while preserving required FARender boilerplate. First external receipt scored 15.33% in 256x256 bounds -2..2 while Aquarium still binned raw centers; after fixing JWildfire coefs packing (`a b d e c f`) and FARender's disc angle convention (`atan2(x,y)`), the raw-center score reached 26.87%. With the candidate switched to full SDF-reservoir density, the same target scored 22.14% at 42.053 ms/frame with all 2M reservoir rows refreshed. Cutting the false JWildfire `normal` -> `linear` import and resolving subpixel SDF envelopes as at least one histogram bin moved the score to 31.36% at 41.692 ms/frame. Aquarium-vs-CPU still scores about 89.94%, so the live failure is exact JWildfire variation/camera/filter semantics, target density weighting, and view-conditioned reservoir feedback, not sample count.",
|
|
"JWildfire selftest is now the flame renderer faceplant target. The current dialect slice supports JWildfire coefficient layout, variationGroup, disc, julian, gaussian_blur, and post transforms. After post lowering, the depth-64 GTX 1070 receipt scores 84.19% against Aquarium's CPU slice oracle in bounds -8..8 and 88.01% in bounds -128..128, but costs about 129 ms/frame. This is not external JWildfire visual parity; it is CPU/GPU agreement on the supported slice. Aquarium still needs richer dialect semantics, palette/density/render-filter parity, weighting-field handling, and persistent per-sample GPU iteration-state reservoirs instead of replaying deep chaos-game ancestry from zero for every splat.",
|
|
"Flame imports must report translation loss. FractalFlameFileParser.ParseFirstWithReport returns accepted, approximated, ignored, and rejected fields per transform, and receipt runs write fractal-flame-import-report-*.json. The JWildfire selftest report currently shows 15 accepted fields, 3 approximations, 45 ignored render/presentation fields, and 11 rejected geometry/sampling fields: wfield_* weighting-field attributes. Treat successful XML parsing as insufficient until rejected geometry fields are either implemented as DSL/operator nodes or explicitly accepted as out-of-scope diagnostics.",
|
|
"Persistent flame iteration now has both a CPU parity contract and a GPU realization. FractalFlameIterationState plus FractalFlameIterationStepper prove chunked CPU advancement; AquariumPackedFractalFlameState mirrors the point/support/material/RNG/step packet in D3D12FractalReservoirCompute as a UAV so flame splats advance over frames. Keep the acquisition/maintenance split explicit in receipts and renderer budgets.",
|
|
"Zyphos' primary planetary terrain test path is now the fractal reservoir surface. The direct SDF planet and Umbros proxy shaders are removed from the render plan; only the parent star remains as a direct SDF body/light. If the planet looks wrong, fix the reservoir lowering/shading path instead of letting the old SDF terrain hide it.",
|
|
"The GPU splat receipt harness lives at tools/Aquarium.Fractal.Receipt and scripts/fractal-splat-receipt.ps1. The live receipt allocates one 80-byte packed SDF splat UAV plus three distinct 64-byte reservoir UAVs for SDF envelopes, PBR material envelopes, and radiosity; those reservoirs are sampled in independent compute passes under a stochastic update budget. On the local NVIDIA GTX 1070 it kept 2,000,000 splats and 2,000,000 reservoirs per layer resident. The fallback hash-fractal receipt updated 50,000 entries per layer with 2 candidates/update at 4.471 ms/frame, 223.7 FPS equivalent. The authored precomposed selected-cut receipt used depth 48, 4 compact transforms, and 15,000 updates per layer at 4.908 ms/frame, 203.7 FPS equivalent, with full reservoir coverage in 133.3 frames. D3D12FractalSplatRender consumes the raw splat, SDF, PBR, and radiosity buffers through separate graphics SRVs for the visible debug subset. This proves compute-side GPU residency, budgeted temporal convergence, authored-program splat population decoupled from domain ancestry depth, and first layered GPU consumption; final terrain/material/radiosity shading is still future work.",
|
|
"FractalProjectedSdfSplatCompiler is the Phase G 2D-projected-to-3D lowering seam: it converts resident SignedDistance2D page payload samples into compact 3D SDF splats through an explicit page-local Vector2 -> Vector3 mapping, surface normal, support radius, and splat budget. Zyphos caches a bounded first set with a flat local mapping until cube-sphere/torus mappers are added.",
|
|
"Zyphos camera distance limits belong to the selected spatial domain, not one global planetary clamp. Leaf/pebble domains must be able to zoom below whole-body distances, and the parent star must be a visible SDF body when it is also the primary light source.",
|
|
"The consolidated fractal brush architecture lives in research/rendering/fractal-brush-architecture-plan.md. Its pipeline is client intent -> domain roots -> semantic IFS brush grammar -> ownership tree -> node summaries -> contribution cache/residency scheduler -> backend packets -> renderer passes -> debug/evidence. Its credibility depends on module boundaries and tests: contracts, pure CPU fractal core, D3D12 backend, client adapters, mock payload/probe/random/clock seams, shader parity tests, and deterministic performance fixtures.",
|
|
"The Perfect Machine waterfall architecture lives in docs/perfect-machine-architecture.md. Treat it as the design authority before expanding SDF splat backends, sensor-fusion candidate adapters, reservoir guide buffers, occupancy graph state, resource-tier residency, or stochastic learned priority. Its core split is domains -> evidence candidates -> target evaluation -> ReSTIR/GRIS reservoirs -> occupancy graph -> residency -> 2D/3D/projected SDF splat packets -> TAA guide buffers.",
|
|
"AquariumFractalSurfacePageKey and AquariumFractalSurfacePage are the renderer-agnostic page contracts for Phase E: height, SignedDistance2D, material, and confidence surface pages carry stable domain/node/kind/mip keys, bounds, dimensions, payload handles, and max error before any D3D12 page store exists.",
|
|
"FractalSurfacePagePlanner lowers selected IFS cuts into stable surface page metadata without renderer dependencies. ZyphosFractalRenderPlan now exposes height, SignedDistance2D, material, and confidence pages beside brushes, resource plans, and structural probe reservoirs; the actual page store, eviction, atlas, and D3D12 lowering are still open.",
|
|
"FractalSurfacePageResidencyPlanner is the renderer-agnostic page-store policy boundary: it asks IFractalSurfacePageStore about page-key residency, keeps best max-error-per-byte resident pages under a byte budget, requests highest-value missing pages, and reports evictions. Zyphos carries this page residency plan, but real storage and D3D12 atlas mutation remain future work.",
|
|
"FractalSurfacePageRasterizer lowers resident planned pages into CPU sample payloads using the shared FractalBrushEnvelope2D math: height sums amplitudes, SignedDistance2D uses a cheap signed support-distance estimate, material uses deterministic weighted claim tags/seeds, and confidence accumulates clamped envelope coverage. Zyphos caches resident page payloads by page key before any GPU atlas exists.",
|
|
"The actionable fractal brush roadmap lives in research/rendering/fractal-brush-implementation-roadmap.md. Start with the first work packet: add Aquarium.Engine.Fractal and tests, cube-face/tile key types, identity and tangent projection candidates, an area distortion sampler, face-edge tests, and a projection report before touching recursive detail."
|
|
],
|
|
"text_and_ui": [
|
|
"Overlay text uses DirectWrite/Direct2D after scene rendering. It is crisp final-pixel UI for debug surfaces, terminals, inspectors, and splash/status text.",
|
|
"Aquarium UI controls follow the CultLib code-first binding style without Unity prefab assumptions: panels, sections, sliders, toggles, buttons, option rows, tree items, and text boxes bound by explicit read/write delegates.",
|
|
"Aquarium.Engine.Contracts exposes AquariumUiDocument as the client-facing debug composition surface. Client panels are tabs inside the single Aquarium debug panel unless they explicitly opt into floating/proximity-faded overlay behavior. Clients can register terminal commands through AquariumUiDocument.Command. Longer editable strings should use AquariumUiTextBox instead of pretending to be row values. Text boxes own caret/selection editing state, may opt into bundled Ubuntu Sans Mono and bottom alignment, and focused text boxes capture input so renderer debug hotkeys and client camera controls stay quiet while editing.",
|
|
"Use AquariumUiTreeItem for selectable hierarchy rows: disclosure arrows own expansion, row selection owns mode/target choice, and clients provide depth/detail/selected bindings without leaking domain-specific hierarchy policy into DebugUi.",
|
|
"The unified F2 debug panel is titled Debug and owns engine controls, client tabs, and a bottom-aligned multiline command terminal. Tab navigation is panel chrome: a highlighted row of buttons below the title, not a content section made of ordinary controls. Do not reintroduce separate Aquarium/Epiphany debug panels fighting for the same hotkey.",
|
|
"Vortice.Mathematics.Rect uses x, y, width, height. UI code should use explicit RectFromEdges helpers when reasoning in edges.",
|
|
"Debug UI feedback needs honest element-specific states: base, hover, and active. Sliders respond on track/fill and handle separately, keep geometry stable, and brighten by lerping accent colors toward white.",
|
|
"Scene/diegetic labels should use renderer-owned MSDF/SDF billboards when they live in world space. Overlay text should not be shoved into HDR for convenience."
|
|
],
|
|
"audio": [
|
|
"Aquarium exposes an optional audio/synth hosting boundary through contracts; clients declare intent, Aquarium schedules playback and owns device output.",
|
|
"Aquarium consumes AquaSynth.Faust as a pinned repo-local NuGet package, with AquaSynth.Core arriving transitively for the built-in patch editor/parser surface. AquaSynth owns synth internals, live patch compilation, native Faust factory lifetime, generated DSP manifests, and tests; AquariumSynthHost owns debounce, trigger scheduling, rendered-buffer caching, and WASAPI playback. Update the package only by deliberate version bump so visual/renderer work can continue while synth construction changes underneath."
|
|
],
|
|
"state_and_reload": [
|
|
"CultCache is the client memory organ. Runtime state, camera, renderer knobs, body state, UI state, and future Epiphany connection state should be typed Cult documents.",
|
|
"Global graphics presentation settings live in epiphany.aquarium.graphics_settings. The debug UI edits the renderer copy; the host syncs changed renderer settings back to the client runtime; the runtime flushes dirty settings through CultCache.",
|
|
"A truncated or unreadable single-file CultCache backing store is not a schema migration failure. Aquarium should quarantine the corrupt snapshot and boot fresh typed state.",
|
|
"dev-reload builds disposable apphost slots so a running window does not lock normal build output. Headless smoke runs use a separate CultCache from the visible dev window.",
|
|
"Live runtime reload is not successful just because dev-watch wrote live-current.txt. The watcher must see the host acknowledge the exact live DLL path in stdout.",
|
|
"Shader reload failure must keep the previous good shader objects bound. Live-runtime reload failure must keep the previous runtime alive."
|
|
]
|
|
},
|
|
"warnings": [
|
|
"A clean repo can still grow Jenga if state and docs lag behind code.",
|
|
"Do not add a framework-shaped dependency just to borrow one comfortable tool.",
|
|
"Do not let bloom or overlay debug output disguise a bad lighting equation.",
|
|
"Do not preserve historical branch scars in live docs unless they change a current decision."
|
|
]
|
|
}
|