render2d: Headless-Rendering — PNG ohne Fenster + Golden-Image-Test
HeadlessRenderer (Feature headless) baut Instance/Adapter/Device ohne Surface (Vulkan, kein Display-Server); render_to_image rendert in eine Rgba8Unorm-Texture (non-sRGB wie ColorMode::Web) und liest mit 256-Byte- Row-Padding zurueck. Draw-Code unveraendert geteilt mit dem Fenster-Pfad. CLI-Bin render_png (Demo-Szene, 990x630); Demo additiv um 45-Grad- Schraffur, Tuerblatt und Schwenkbogen erweitert, damit das Golden alle Pfade abdeckt. Golden-Test mit eingechecktem Referenzbild: 0/623700 Pixel Abweichung, bit-exakt reproduzierbar; bei Abweichung Diff-Dump nach target/. Doku in docs/design/engine-headless.md.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// CLI-Beweis fuer den Headless-Renderpfad (Feature "headless"): rendert die
|
||||
// Demo-Szene (dieselbe wie der Fenster-Spike, `demo::demo_scene`) OHNE Fenster in
|
||||
// eine PNG-Datei. Belegt, dass `HeadlessRenderer` unabhaengig von einer Display-
|
||||
// Session funktioniert.
|
||||
//
|
||||
// Start: cargo run --features headless --bin render_png -- [--out PFAD] [--width N] [--height N]
|
||||
#![cfg(feature = "headless")]
|
||||
|
||||
use render2d::headless::HeadlessRenderer;
|
||||
use render2d::{demo_scene, initial_view_box};
|
||||
|
||||
fn main() {
|
||||
// Defaults passend zum Seitenverhaeltnis von `initial_view_box` (990x630 —
|
||||
// Bildschirm-Raum-Einheiten der Demo-Szene, siehe demo.rs).
|
||||
let mut width = 990u32;
|
||||
let mut height = 630u32;
|
||||
let mut out = String::from("target/headless-demo.png");
|
||||
|
||||
let mut args = std::env::args().skip(1);
|
||||
while let Some(arg) = args.next() {
|
||||
match arg.as_str() {
|
||||
"--width" => {
|
||||
width = args
|
||||
.next()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(width);
|
||||
}
|
||||
"--height" => {
|
||||
height = args
|
||||
.next()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(height);
|
||||
}
|
||||
"--out" => out = args.next().unwrap_or(out),
|
||||
other => eprintln!("render_png: unbekanntes Argument ignoriert: {other}"),
|
||||
}
|
||||
}
|
||||
|
||||
let mut renderer = HeadlessRenderer::new().expect("Headless-Renderer initialisieren");
|
||||
let image = renderer.render_to_image(&demo_scene(), width, height, initial_view_box(), 100.0);
|
||||
let png = image.encode_png();
|
||||
|
||||
if let Some(parent) = std::path::Path::new(&out).parent() {
|
||||
if !parent.as_os_str().is_empty() {
|
||||
std::fs::create_dir_all(parent).expect("Ausgabeverzeichnis anlegen");
|
||||
}
|
||||
}
|
||||
std::fs::write(&out, &png).expect("PNG schreiben");
|
||||
println!("render_png: geschrieben nach {out} ({width}x{height})");
|
||||
}
|
||||
Reference in New Issue
Block a user