extends SceneTree ## Native renderer review of a scripted walk through the actual loaded meadow. ## The capture moves presentation only and verifies the simulation checksum. const OUTPUT := "res://docs/baselines/foliage_" func _initialize() -> void: call_deferred("_run") func _run() -> void: root.size = Vector2i(1600, 900) var main := load("res://main.tscn").instantiate() as Node3D main.get_node("SimulationManager").set("debug_logs", false) root.add_child(main) await process_frame var manager := main.get_node("SimulationManager") manager.set_process(false) var checksum: String = manager.get_state_checksum() var world := main.get_node("JajceWorld") as JajceWorld world.apply_presentation_quality(JajceWorld.PresentationQuality.HIGH) var controller := world.grass_controller controller.set_process(false) var cycle := world.get_node("DayNightCycle") cycle.set_process(false) cycle.call("_apply_light_rotation", 0.4) cycle.call("_apply_environment", 0.4) for layer in main.get_children(): if layer is CanvasLayer: layer.hide() for actor in get_nodes_in_group("grass_interactors"): actor.set_physics_process(false) actor.set_process(false) var player := main.get_node("Player") as CharacterBody3D player.get_node("Visual/Sword").hide() main.get_node("CameraRig").set_physics_process(false) var camera := root.get_camera_3d() camera.reparent(main) camera.global_position = Vector3(16, 7.5, 23) camera.look_at(Vector3(11, 0.6, 10.5)) camera.fov = 48 player.position = Vector3(5, 0, 10.85) player.get_node("Visual").rotation.y = -PI / 2.0 for _frame in 90: await process_frame # Freeze wind and particles so the four review frames isolate contact deformation. Engine.time_scale = 0.0 var demo := main.get_node("DemoController") if demo.get("debug_overlay_visible"): demo.call("toggle_debug_overlay") for layer in main.get_children(): if layer is CanvasLayer: layer.hide() controller.call("reset_interaction") await _save("before.png") var update_times: Array[float] = [] for step in 61: player.position.x = 5.0 + step * 0.18 player.position.y = world.terrain.data.get_height(player.position) + 0.02 var start := Time.get_ticks_usec() controller.call("_refresh_interactors", 0.08) update_times.append(float(Time.get_ticks_usec() - start) / 1000.0) for _frame in 5: await process_frame if step == 37: await _save("contact.png") await _save("trail.png") var active_cells := (controller.get("_trail_map").get("_cells") as Dictionary).size() var draws := Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME) for _step in 110: controller.call("_refresh_interactors", 0.08) for _frame in 5: await process_frame await _save("recovered.png") update_times.sort() var report := { "renderer": RenderingServer.get_current_rendering_driver_name(), "resolution": "1600x900", "profile": "High", "workload": "Actual Jajce meadow; 8 nearest actors, player presentation follows an 11 m sweep", "controller_update_p50_ms": update_times[30], "controller_update_p95_ms": update_times[57], "active_trail_texels": active_cells, "trail_texture_bytes": 128 * 128 * 16, "draw_calls": draws, "simulation_checksum_unchanged": manager.get_state_checksum() == checksum, "note": "CPU timing includes scanning, field painting and material uploads; not isolated GPU frame time." } var file := FileAccess.open(OUTPUT + "render_metrics.json", FileAccess.WRITE) file.store_string(JSON.stringify(report, "\t") + "\n") print(JSON.stringify(report)) assert(manager.get_state_checksum() == checksum) main.free() Engine.time_scale = 1.0 await process_frame quit(0) func _save(filename: String) -> void: await RenderingServer.frame_post_draw var capture := root.get_texture().get_image() assert(not capture.is_empty()) assert(capture.save_png(OUTPUT + filename) == OK)