docs: capture jajce lookdev baseline

This commit is contained in:
2026-07-08 16:01:08 +02:00
parent 324084f233
commit 0fa8d80119
8 changed files with 140 additions and 3 deletions
+4 -2
View File
@@ -629,11 +629,13 @@ Completed:
9. Terrain3D-derived playable-loop navigation: `JajceWorld` now uses an
external baked navigation resource generated from Terrain3D source geometry,
and runtime tests reject partial paths that do not reach their targets.
10. `Jajce Lookdev 01` capture and review: a reproducible capture tool writes
the daytime lookdev baseline to `docs/baselines/jajce_lookdev_01.png`, and
the review notes the current strengths and visual follow-ups.
Next:
1. Capture and visually review “Jajce Lookdev 01.”
2. Capture “Simulation Garden 01.”
1. Capture “Simulation Garden 01.”
Do not start with GIS data, a full city, a large asset pack, or more NPC
mechanics. The next proof is a beautiful stage for the systems that already
+2
View File
@@ -678,6 +678,8 @@ Recently completed:
Terrain3D-derived navigation mesh resource generated by
`tools/bake_jajce_navigation.gd`; route tests now also reject partial paths
that do not reach their requested targets.
- `Jajce Lookdev 01` is captured and reviewed with a project-owned capture
script and a daytime baseline image under `docs/baselines/`.
This order strengthens the simulation while regularly producing visible
progress suitable for public development updates.
+7 -1
View File
@@ -195,6 +195,9 @@ study, and patrol target typed activity sites. The migration is documented in
- **Jajce runtime:** reusable 512 m Terrain3D seed, greybox landmarks, stable
ResourceNode placement, lookdev camera, and Terrain3D-derived runtime
navigation with collision guardrails
- **Lookdev baseline:** `Jajce Lookdev 01` is captured at
`docs/baselines/jajce_lookdev_01.png` with
`tools/capture_jajce_lookdev.gd`
- **Terrain compatibility floor:** Godot 4.4 according to the bundled extension
- **Version control:** Git
- **Primary branch:** `main`
@@ -334,6 +337,8 @@ distance with resource `safety_risk`, `comfort_distance`, and
their targets, and compare required navigation paths against the Terrain3D
height field;
- a look-development scene and camera.
- a reproducible daytime lookdev capture and review note under
`docs/baselines/`.
This is a runtime integration proof, not the final terrain composition.
Terrain3D startup requires several physics frames before reliable
@@ -544,7 +549,8 @@ These are expected prototype constraints, not necessarily isolated bugs:
playable-loop pass, so future terrain sculpting should rerun the bake tool and
recheck reachability rather than hand-editing navigation polygons.
- Terrain3D and the bounded Jajce beauty baseline now run in the main game
scene; final visual review and character/profession readability remain.
scene; `Jajce Lookdev 01` is captured, while the runtime `Simulation Garden
01` capture remains the next presentation checkpoint.
- Combat, companions, factions, politics, trade, rumours, quests, persistence,
and regional travel do not yet exist.
- Placeholder geometry is sufficient for debugging but not for build-in-public
+46
View File
@@ -0,0 +1,46 @@
# Jajce Lookdev 01
- **Captured:** 2026-07-08
- **Scene:** `res://world/jajce/JajceLookdev.tscn`
- **Image:** [`jajce_lookdev_01.png`](jajce_lookdev_01.png)
- **Capture tool:** `res://tools/capture_jajce_lookdev.gd`
## Contract
This checkpoint captures the first readable Jajce visual stage after the
Terrain3D-derived navigation pass. It is a visual composition baseline, not a
gameplay regression test.
The image should show:
- the broad shaped valley terrain;
- the village and fortress blockouts;
- water, waterfall/foam, and bridge silhouettes;
- visible foliage clusters;
- warm daylight/fog treatment;
- stable enough framing to compare future terrain, lighting, and asset passes.
## Review
The scene now reads as a coherent daytime valley rather than the previous dark
startup view. The terrain, homes, bridge, water, waterfall, smoke/mist, and
first foliage clusters are all visible in one frame.
Known follow-up work:
- reduce the heavy haze if it hides terrain color and landmark silhouettes;
- improve fortress/waterfall readability from the beauty-camera angle;
- replace blockout architecture and placeholder resource markers gradually;
- capture a runtime `Simulation Garden 01` view with active NPC behavior.
## Command
Run with a real display driver, not `--headless`; headless Godot uses the dummy
renderer on this machine and cannot read back a viewport image.
```powershell
$env:APPDATA = "$PWD\logs\quality\godot_profile"
$env:LOCALAPPDATA = "$PWD\logs\quality\godot_profile"
& "C:\Users\Rijad\Downloads\tools\Godot_v4.7-stable_win64.exe\Godot_v4.7-stable_win64_console.exe" `
--path "$PWD" --script res://tools/capture_jajce_lookdev.gd
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 732 KiB

+71
View File
@@ -0,0 +1,71 @@
extends SceneTree
const OUTPUT_PATH := "res://docs/baselines/jajce_lookdev_01.png"
const SCENE_PATH := "res://world/jajce/JajceLookdev.tscn"
const CAPTURE_SIZE := Vector2i(1280, 720)
const WARMUP_FRAMES := 90
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
root.size = CAPTURE_SIZE
var scene := load(SCENE_PATH) as PackedScene
if scene == null:
push_error("Could not load %s" % SCENE_PATH)
quit(1)
return
var lookdev := scene.instantiate() as Node3D
root.add_child(lookdev)
await process_frame
for _frame in WARMUP_FRAMES:
await process_frame
var image := root.get_texture().get_image()
if image == null or image.is_empty():
push_error("Lookdev capture produced no image")
quit(1)
return
var analysis := _analyze_image(image)
if analysis.get("range", 0.0) < 0.05:
push_error("Lookdev capture is too uniform: %s" % analysis)
quit(1)
return
var error := image.save_png(OUTPUT_PATH)
if error != OK:
push_error("Could not save %s: %s" % [OUTPUT_PATH, error_string(error)])
quit(1)
return
print("[TOOL] Saved %s | %s" % [OUTPUT_PATH, analysis])
quit(0)
func _analyze_image(image: Image) -> Dictionary:
var min_luma := INF
var max_luma := -INF
var total_luma := 0.0
var samples := 0
var step_x = maxi(1, image.get_width() / 64)
var step_y = maxi(1, image.get_height() / 36)
for y in range(0, image.get_height(), step_y):
for x in range(0, image.get_width(), step_x):
var color := image.get_pixel(x, y)
var luma := color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722
min_luma = minf(min_luma, luma)
max_luma = maxf(max_luma, luma)
total_luma += luma
samples += 1
return {
"size": "%sx%s" % [image.get_width(), image.get_height()],
"samples": samples,
"average_luma": total_luma / samples,
"range": max_luma - min_luma,
}
+3
View File
@@ -7,6 +7,9 @@
[node name="JajceWorld" parent="." instance=ExtResource("1_world")]
[node name="DayNightCycle" parent="JajceWorld" index="9"]
initial_cycle = 0.38
[node name="BeautyCamera" type="Camera3D" parent="."]
position = Vector3(44, 34, 44)
current = true
+7
View File
@@ -1,6 +1,7 @@
extends Node
@export var cycle_duration_seconds := 240.0
@export_range(0.0, 1.0, 0.01) var initial_cycle := 0.35
@export var directional_light: DirectionalLight3D
@export var world_environment: WorldEnvironment
@@ -37,6 +38,12 @@ const SUNRISE_SUNSET_ENERGY := 0.8
var elapsed := 0.0
func _ready() -> void:
elapsed = cycle_duration_seconds * initial_cycle
_apply_light_rotation(initial_cycle)
_apply_environment(initial_cycle)
func _process(delta: float) -> void:
elapsed += delta
if elapsed >= cycle_duration_seconds: