WebGPU tile rendering for Rio Terminal via wgpu and sugarloaf. Extends OSC 1337 for GPU shaders in terminal regions. Use when implementing terminal graphics, custom shaders, or GPU-accelerated terminal UI.
/plugin marketplace add plurigrid/asi/plugin install plurigrid-asi-skills@plurigrid/asiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
reference/protocol.mdreference/shaders.mdGPU-accelerated tile rendering in Rio Terminal using wgpu and the sugarloaf brush architecture.
OSC 1337 Sequence → rio-backend (parse) → RioEvent::InsertTile → rioterm (frontend) → sugarloaf TileBrush → wgpu render
| File | Purpose |
|---|---|
sugarloaf/src/components/tiles/mod.rs | TileBrush, TileWorldState, GPU buffers |
sugarloaf/src/sugarloaf.rs | Main renderer integration, public API |
rio-backend/src/ansi/tile_protocol.rs | OSC 1337 Tile= parsing |
rio-backend/src/performer/handler.rs | OSC dispatch to handler |
rio-backend/src/event/mod.rs | InsertTile event variant |
frontends/rioterm/src/application.rs | Frontend event handling |
# Format: ESC ] 1337 ; Tile = key:value,key:value,... BEL
printf '\033]1337;Tile=shader:plasma,x:50,y:50,w:200,h:150\007'
| Key | Type | Description |
|---|---|---|
shader | string | plasma, clock, noise, or custom ID |
x, y | f32 | Position in pixels |
w, h | f32 | Size in pixels |
id | u64 | Tile ID (0 = auto-assign) |
kind | string | persistent (default) or transient |
r, g, b, a | f32 | Custom color/data (0.0-1.0) |
time_offset | f32 | Animation time offset |
Remain until explicitly removed by ID:
let id = sugarloaf.create_persistent_tile(scene);
// ... later
sugarloaf.remove_persistent_tile(id);
Cleared at begin_frame(), must be re-pushed each frame:
sugarloaf.push_transient_tile(scene);
Manages CPU state with high-precision time (f64), converted to modular f32 for GPU:
pub struct TileWorldState {
persistent: HashMap<TileId, TileScene>,
transient: Vec<TileScene>,
world_time_seconds: f64,
next_id: TileId,
}
impl TileWorldState {
pub fn begin_frame(&mut self, dt_seconds: f64) {
self.world_time_seconds += dt_seconds;
self.transient.clear();
}
}
Uniform structure available in shaders:
struct Uniforms {
position: vec2<f32>, // NDC position
size: vec2<f32>, // NDC size
time: f32, // Animation time (modular)
custom: vec4<f32>, // r,g,b,a from protocol
}
@group(0) @binding(0) var<uniform> u: Uniforms;
@vertex
fn vs_main(@location(0) pos: vec2<f32>, @location(1) uv: vec2<f32>) -> VertexOutput {
var out: VertexOutput;
let screen_pos = u.position + pos * u.size;
out.position = vec4<f32>(screen_pos, 0.0, 1.0);
out.uv = uv;
return out;
}
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let t = u.time;
// Your shader logic using in.uv, t, u.custom
return vec4<f32>(color, 1.0);
}
# Plasma effect
printf '\033]1337;Tile=shader:plasma,x:50,y:50,w:200,h:150,r:0.5,g:0.2,b:0.8\007'
# Clock display
printf '\033]1337;Tile=shader:clock,x:300,y:50,w:250,h:80\007'
# Remove by ID
printf '\033]1337;Tile=remove:42\007'
InsertTile(TileSpec)begin_frame(dt) before each renderSee reference/shaders.md for complete plasma, clock, and noise shader implementations.