2026-05-23 10:06:37 +02:00
2026-05-16 00:00:33 +02:00
2026-05-23 10:06:37 +02:00
2026-05-15 22:58:42 +02:00
2026-05-22 15:00:08 +02:00
2026-05-22 15:00:08 +02:00
2026-05-23 10:06:37 +02:00

pbio: simple pixel buffer and I/O system

Pixelbuffer-basiertes Fenster mit Palette-Lookup-Renderer (winit + wgpu) und Maus/Tastatureingaben.

pbio nimmt einen Bytearray, interpretiert diesen als 8-Bit-Pixelbuffer und rendert ihn auf ein Fenster. Optional mit Letterbox für ein festes Seitenverhältnis.

Integration

pbio ist nicht auf crates.io veröffentlicht. Das Crate kann direkt aus dem Git-Repository eingebunden werden:

[dependencies]
pbio = { git = "https://codeberg.org/irrlicht/rust-pbio.git" }

pbio braucht keine System-Libraries zum Bauen — winit lädt X11/Wayland zur Laufzeit per dlopen. Zur Laufzeit reichen aktuelle Grafiktreiber mit Vulkan-, Metal- oder DX12-Unterstützung für wgpu.

Verwendung

use pbio::{Event, Key, Platform, PlatformConfig};

fn main() {
    let mut p = Platform::new(PlatformConfig {
        title:            "Demo".into(),
        window_size:      (1024, 768),
        framebuffer_size: (320, 240),
        ..Default::default()
    });

    while !p.should_close() {
        p.poll_events(None);

        // drain_events() borrowt &mut self → close erst nach dem Loop setzen.
        let mut close = false;
        for ev in p.drain_events() {
            if let Event::Key { key: Key::Escape, pressed: true, .. } = ev {
                close = true;
            }
        }
        if close { p.request_close(); }

        let (w, _h) = p.framebuffer_size();
        let fb = p.framebuffer_mut();
        for (i, px) in fb.iter_mut().enumerate() {
            *px = ((i as u32 % w) ^ (i as u32 / w)) as u8;
        }

        p.present();
    }
}

API-Überblick

  • PlatformConfig Titel, Fenster-/Framebuffer-Größe, optionales aspect_ratio (Letterbox), Palette, VSync, mouse_visible, mouse_capture. Default = 800×600 Fenster, 320×240 Framebuffer, 4:3, palette::RGB332.
  • Platform::new(cfg) Fenster + GPU-Pipeline aufsetzen.
  • poll_events(timeout) winit-Events einlesen (None = blockierend).
  • drain_events() Iterator über Event (Key, Char, MouseMove, MouseBtn, Resize, CloseRequested).
  • framebuffer_mut() &mut [u8] der Länge w*h, je Pixel ein Paletten-Index.
  • palette_mut() / palette() &mut [[u8; 3]; 256] bzw. &[...]; Schreibzugriff markiert die Palette dirty, der nächste present() lädt sie hoch.
  • present() Frame auf das Fenster bringen.
  • should_close() / request_close().
  • set_mouse_visible(bool) Cursor anzeigen oder verstecken (freie Bewegung).
  • set_mouse_capture(bool) Cursor einsperren + verstecken (winit CursorGrabMode::Locked, Fallback Confined), liefert unbegrenzte Bewegungsdeltas via mouse_delta(). Impliziert mouse_visible = false. Im Capture-Mode ist Event::MouseMove nicht sinnvoll (eingefrorene oder am Fensterrand klemmende Werte) — stattdessen mouse_delta() benutzen.
  • mouse_delta() -> (f32, f32) akkumulierte Mausbewegung seit dem letzten Aufruf in Framebuffer-Pixeln (gleiche Skala wie MouseMove), danach genullt. Nützlich für FPS-Kamerasteuerung.

Cursor-Modi

mouse_visible mouse_capture winit-Modus Einsatz
true false sichtbar, frei Standard-UI
false false versteckt, frei Eigener Cursor im Framebuffer
* true Locked / Confined, versteckt FPS-Kamera, unbegrenzte Deltas
// FPS-Kamera
p.set_mouse_capture(true);
let (dx, dy) = p.mouse_delta();
yaw   += dx * sensitivity;
pitch += dy * sensitivity;

Paletten

palette::RGB332 ist als Default eingebaut. Eigene Paletten sind ein [[u8; 3]; 256] (RGB pro Index) und werden über PlatformConfig::palette übergeben.

Zur Laufzeit kann die Palette über palette_mut() modifiziert werden — einzelne Einträge oder die komplette Tabelle. Der Upload passiert automatisch im nächsten present():

p.palette_mut()[42] = [255, 0, 0];  // Slot 42 → rot
p.present();
S
Description
Simple 8-bit pixel buffer and input/output system.
Readme 129 KiB
Languages
Rust 95.3%
WGSL 3.7%
Python 1%