16-Bit-Truecolor (RGB565) statt 8-Bit-Palette

Framebuffer ist jetzt &mut [u16], jeder Wert ein RGB565-Pixel. Der
Shader dekodiert die Bitfelder direkt aus einer R16Uint-Textur; die
Palette (Textur, API, Presets, Tooling) entfaellt. Neu: pbio::rgb565()
zum Packen von 8-Bit-Kanaelen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-05 15:04:05 +02:00
parent 2d81471820
commit c5a4d0026b
6 changed files with 60 additions and 128 deletions
+19 -21
View File
@@ -1,8 +1,10 @@
# pbio: simple pixel buffer and I/O system
# pbio: simple pixel buffer and I/O system — 16-Bit-Truecolor-Variante
Pixelbuffer-basiertes Fenster mit Palette-Lookup-Renderer (winit + wgpu) und Maus/Tastatureingaben.
Pixelbuffer-basiertes Fenster mit RGB565-Truecolor-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.
pbio nimmt ein `u16`-Array, interpretiert jeden Wert als RGB565-Pixel (Bits `RRRRRGGGGGGBBBBB`) und rendert ihn auf ein Fenster. Optional mit Letterbox für ein festes Seitenverhältnis.
Dies ist der Branch `truecolor16`. Auf `master` liegt die 8-Bit-Variante mit Palette-Lookup — beide sind unabhängig voneinander nutzbar.
## Integration
@@ -10,7 +12,7 @@ pbio ist nicht auf crates.io veröffentlicht. Das Crate kann direkt aus dem Git-
```toml
[dependencies]
pbio = { git = "https://codeberg.org/irrlicht/rust-pbio.git" }
pbio = { git = "https://codeberg.org/irrlicht/rust-pbio.git", branch = "truecolor16" }
```
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.
@@ -40,7 +42,8 @@ fn main() {
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;
let v = ((i as u32 % w) ^ (i as u32 / w)) as u8;
*px = pbio::rgb565(v, v, v);
}
p.present();
@@ -51,21 +54,20 @@ fn main() {
## 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`.
`aspect_ratio` (Letterbox), VSync, `mouse_visible`, `mouse_capture`.
Default = 800×600 Fenster, 320×240 Framebuffer, 4:3.
- `Platform::new(cfg)` Fenster + GPU-Pipeline aufsetzen.
- `poll_events(timeout)` winit-Events einlesen (`None` = blockierend).
- `poll_event() -> Option<Event>` ein Event aus der Queue holen. Gibt
`&mut self` nach jedem Call frei, sodass im Loop direkt auf die Platform
reagiert werden kann (`request_close`, `set_mouse_capture`, `palette_mut` …).
reagiert werden kann (`request_close`, `set_mouse_capture` …).
Empfohlen für die normale Event-Schleife.
- `drain_events()` Iterator über `Event` (`Key`, `Char`, `MouseMove`,
`MouseBtn`, `Resize`, `CloseRequested`). Borrowt `&mut self` bis der
Iterator fertig ist — Reaktionen auf die Platform müssen dann nach dem
Loop angewandt werden. Nützlich für reines Loggen/Filtern.
- `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.
- `framebuffer_mut()` `&mut [u16]` der Länge `w*h`, je Pixel ein RGB565-Wert.
- `rgb565(r, g, b) -> u16` packt 8-Bit-RGB in einen RGB565-Pixelwert (const fn).
- `present()` Frame auf das Fenster bringen.
- `should_close()` / `request_close()`.
- `set_mouse_visible(bool)` Cursor anzeigen oder verstecken (freie Bewegung).
@@ -94,17 +96,13 @@ yaw += dx * sensitivity;
pitch += dy * sensitivity;
```
## Paletten
## Pixelformat
`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()`:
RGB565: 5 Bit Rot, 6 Bit Grün, 5 Bit Blau in einem `u16` (Bits
`RRRRRGGGGGGBBBBB`). Der Shader dekodiert die Bitfelder direkt — es gibt
keine Palette. Zum Packen von 8-Bit-Kanälen dient `pbio::rgb565`:
```rust
p.palette_mut()[42] = [255, 0, 0]; // Slot 42 → rot
p.present();
let orange = pbio::rgb565(255, 160, 0);
p.framebuffer_mut()[0] = orange;
```