feat(environment): add painterly skies and living meadows

This commit is contained in:
Rijad Zuzo
2026-09-05 20:27:09 +02:00
parent 7899d36f03
commit ec16e2f2ca
71 changed files with 2280 additions and 213 deletions
+87 -5
View File
@@ -38,11 +38,11 @@ spawn is a next integration.
`JajceWorld` owns reversible High, Balanced, and Low presentation profiles with
instance-local mutable environment/grass resources and viewport-scale ownership.
| Profile | 3D scale | Shadow distance | Volumetric/glow | Grass |
| Profile | 3D scale / MSAA | Shadow distance | Volumetric/glow | Grass |
| --- | ---: | ---: | --- | --- |
| High | authored | authored (currently 180 m) | authored when renderer supports it | authored density/interactors |
| Balanced (default) | 0.85 cap | 120 m cap | authored ordinary lookdev; unsupported volumetric disabled | reduced spacing/interactors/update rate |
| Low | 0.70 cap | 80 m, orthogonal | volumetric/glow/adjustment disabled; ordinary fog retained | hidden/stopped, emitters off, shader interactors zero |
| High | authored / authored 4× | authored (currently 180 m) | authored when renderer supports it | authored density/interactors |
| Balanced (default) | 0.85 cap / 2× cap | 120 m cap | authored ordinary lookdev; unsupported volumetric disabled | reduced spacing/interactors/update rate |
| Low | 0.70 cap / off | 80 m, orthogonal | volumetric/glow/adjustment disabled; ordinary fog retained | hidden/stopped, emitters off, shader interactors zero |
UI remains at native resolution. High/Low switches restore captured authored
values; viewport scale restoration is guarded by the current quality owner so a
@@ -103,7 +103,7 @@ profession tint, velocity-driven motion, inventory cues and death through the
existing presentation controllers. No saved state or navigation changes.
Characters and buildings use soft cel bands; tree crowns retain the shared
breeze with painted color patches. A static procedural cloud sky, cooler
breeze with painted color patches. A painted cloud panorama, cooler
ambient fill and warm sunlight follow the simulation day/night clock. The
cloud shader adds no volumetric pass, outline pass or screen-space postprocess.
See [the asset contract and rebuild commands](../assets/storybook/README.md).
@@ -161,3 +161,85 @@ ledger, not brittle cross-machine CI thresholds.
See [the benchmark ledger](benchmarks/README.md), [regional contract](REGIONAL_SIMULATION.md),
and [the build-in-public visual plan](BUILD_IN_PUBLIC_PLAN.md).
## Painterly environment pass — September 2026
The reference study highlighted flat cloud bands, primitive tree silhouettes,
sparse ground cover, opaque green water, and a sun arc offset from daytime
brightness. The current pass addresses those through shared presentation assets:
- The WorldEnvironment uses cool blue ambient fill, warm sunlight, restrained
glow and ordinary aerial fog. The solar arc now peaks at noon and the warm
transitions overlap dawn/dusk. An original painted cloud panorama supplies
layered cumulus shapes; a static sky shader remaps the artwork, blends its
seam/horizon, and tints it from the simulation clock. It adds no TIME-driven
cubemap updates or volumetric cloud pass. Generation provenance and the exact
prompt are in [the asset guide](../assets/painterly/README.md).
- Original Blender broadleaf crowns/trunks and layered conifers replace the
primitive foliage. Seventeen decorative edge trees form a woodland backdrop.
The four village tree placeholders now use `HarvestableTreePresentation`,
retaining their existing IDs, amounts, interaction points and resource count.
Full/low/depleted state and restored crowns still derive from real amounts.
- `PainterlyMeadow` creates at most 1,680 decorative flower clumps in four
MultiMesh batches, with cream daisies, pink cosmos, buttercups and lavender.
Local seeded drifts follow terrain and exclude houses, paths, work sites and
resource approach points. High/Balanced/Low expose at most 1,680/1,092/536
clumps, with shorter distance fading in cheaper profiles. Flowers share the
prevailing breeze; the existing grass and berry contact field remains intact.
Explicit white instance colors preserve the painted GLB palette when custom
instance data is enabled in Compatibility; native review caught and verified
that renderer-specific regression.
Flowers have no collision, harvesting, actor-contact deformation or saved
state. See [mesh sources and budgets](../assets/meadow/README.md).
- The blue/turquoise river follows actual centerline terrain heights, keeps
level cross-sections, and clips dry edges at the shoreline. The pool and its
outlet meet without overlapping coplanar transparent sheets. Broken foam,
subtle flowing strokes and painted reflection patches replace the hard ring
and featureless surface. These reflections are stylized procedural patches
plus ordinary sky specular response, not exact reflected scene geometry,
screen-space reflections, refraction or depth sampling. Water obeys scene
lighting at night and adds no per-frame scripts.
- MSAA follows the existing viewport ownership rules: High preserves authored
4×, Balanced caps at 2×, and Low disables it. Closing an inactive world cannot
overwrite the active world's antialiasing or an external viewport override.
The editable Blender sources live under `art/painterly/` and `art/meadow/`,
protected by `.gdignore`; runtime consumes portable GLBs. The broadleaf is
5,350 triangles / five surfaces and the conifer is 1,580 / two. All flower
clumps together are capped at 362,880 triangles / four surfaces before
quality and distance reduction. No scene collision, navigation bake, terrain
heightmap, simulation rule or save schema was changed.
`tools/capture_painterly_environment.gd -- --label=after` captures the running
main scene with paused simulation, fixed daytime presentation and hidden HUD,
including the normal gameplay camera, valley, lower village view and night.
The valley/near-village `painterly_before_*` and `painterly_after_*`
images are matched cameras; `after_gameplay` fixes the normal rig at its default
yaw/zoom with mouse input disabled, and `after_vista` is an additional review angle.
The tool also records static-camera profile samples in
`painterly_after_metrics.json`; wall-frame latency includes vsync and is not
isolated GPU time or weak-PC proof. Runtime camera defaults are unchanged.
Remaining visual work is primarily authored terrain/shoreline detail and the
blockout-like building/fortress forms. This pass improves atmosphere and
foliage without treating those assets as finished film-quality environments.
Validation for this pass: the full macOS Godot 4.7 gate passed, including all
headless scenarios, the Compatibility quality scenario, and 182 GUT tests /
2,279 assertions. Main-scene headless startup passed the gate's existing exact
diagnostic allowlist. Native Metal daytime/gameplay/valley/night images were
reviewed at 1600×900, with a separate native Compatibility capture confirming
colored petals after the instance-buffer fix. The presentation-quality scenario
also passed with native Compatibility, including white instance-color readback
(the headless dummy renderer cannot provide that readback).
The static M1 Max sample reports approximately 16.7 ms
median wall-frame time in all three profiles; see its JSON for p95, draw calls
and primitives. This includes vsync and does not establish GPU headroom.
Native renderer shutdown still reports the particle shader/material RID
retention previously documented in the storybook/foliage pass; the headless
allowlist was not expanded. Compatibility has different color/tonemapping and
its existing particle/texture shutdown diagnostics. Metal is the color
reference for the saved art-review images.
The native multi-world quality scenario additionally logged a transient macOS
OpenGL cubemap-unloadable diagnostic; the final main-scene captures did not.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

@@ -0,0 +1,53 @@
{
"device": "Apple M1 Max (Apple7)",
"renderer": "metal",
"resolution": "1600x900",
"samples": [
{
"active_npcs": 6,
"draw_calls": 825.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 1680
},
"msaa_enum": 2,
"primitives": 1070038.0,
"profile": "high",
"render_scale": 1.0,
"wall_frame_p50_ms": 16.649,
"wall_frame_p95_ms": 17.327
},
{
"active_npcs": 6,
"draw_calls": 710.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 1092
},
"msaa_enum": 1,
"primitives": 810830.0,
"profile": "balanced",
"render_scale": 0.850000023841858,
"wall_frame_p50_ms": 16.672,
"wall_frame_p95_ms": 17.06
},
{
"active_npcs": 6,
"draw_calls": 657.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 536
},
"msaa_enum": 0,
"primitives": 645010.0,
"profile": "low",
"render_scale": 0.699999988079071,
"wall_frame_p50_ms": 16.676,
"wall_frame_p95_ms": 17.069
}
],
"workload": "Paused main scene, static valley camera; wall time includes vsync"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 709 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

@@ -0,0 +1,53 @@
{
"device": "Apple M1 Max",
"renderer": "opengl3",
"resolution": "1600x900",
"samples": [
{
"active_npcs": 6,
"draw_calls": 1304.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 1680
},
"msaa_enum": 2,
"primitives": 1070038.0,
"profile": "high",
"render_scale": 1.0,
"wall_frame_p50_ms": 22.166,
"wall_frame_p95_ms": 23.467
},
{
"active_npcs": 6,
"draw_calls": 1166.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 1092
},
"msaa_enum": 1,
"primitives": 810758.0,
"profile": "balanced",
"render_scale": 0.850000023841858,
"wall_frame_p50_ms": 17.903,
"wall_frame_p95_ms": 26.363
},
{
"active_npcs": 6,
"draw_calls": 1084.0,
"meadow": {
"flower_clump_count": 1680,
"multimesh_batch_count": 4,
"visible_flower_clump_count": 536
},
"msaa_enum": 0,
"primitives": 645010.0,
"profile": "low",
"render_scale": 0.699999988079071,
"wall_frame_p50_ms": 13.533,
"wall_frame_p95_ms": 16.623
}
],
"workload": "Paused main scene, static valley camera; wall time includes vsync"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB