Skip to main content

GpuRenderer

Struct GpuRenderer 

Source
pub struct GpuRenderer { /* private fields */ }

Implementations§

Source§

impl GpuRenderer

Source

pub async fn new<W>( window: Arc<W>, size: (u32, u32), settings: GpuRendererSettings, ) -> Result<Self, GpuInitError>
where W: HasWindowHandle + HasDisplayHandle + Send + Sync + 'static,

Stand up the device + surface + swapchain on window. Async because wgpu::Adapter/Device requests are.

window is any raw-window-handle provider (winit, SDL, GLFW, …) wrapped in an Arc; size is its initial physical framebuffer size in pixels — passed explicitly so the renderer stays decoupled from any one windowing library’s size API.

§Errors

Returns GpuInitError if surface creation, adapter selection, or device request fails. Hosts treat any error as “fall back to the CPU path”.

Source

pub fn new_blocking<W>( window: Arc<W>, size: (u32, u32), settings: GpuRendererSettings, ) -> Result<Self, GpuInitError>
where W: HasWindowHandle + HasDisplayHandle + Send + Sync + 'static,

Synchronous wrapper for hosts that don’t have an async runtime. Internally pollster::block_ons Self::new.

§Errors

See Self::new.

Source

pub fn adapter_info(&self) -> &str

Human-readable adapter description — name + backend + device type. The demo host prints this in the title bar.

Source

pub fn device(&self) -> &Device

Borrow the underlying wgpu device — hosts use this to build chunk uploads (GpuChunkResident::upload(gpu.device(), …)).

Source

pub fn queue(&self) -> &Queue

Borrow the wgpu queue — hosts use this for read-back paths (GpuChunkResident::read_voxel_blocking(gpu.device(), gpu.queue(), …)).

Source

pub fn set_sky_panorama(&mut self, rgba: &[u8], width: u32, height: u32)

GPU.8 — upload an equirectangular panorama as the scene’s sky texture. rgba is row-major, width × height pixels, 4 bytes per pixel (R, G, B, A). The shader samples it with u = atan2(dir.x, dir.y) / (2π) + 0.5 (azimuth) and v = acos(-dir.z) / π (elevation), matching standard equirectangular layout (top of image = zenith for voxlap’s +z = down basis).

§Panics

If rgba.len() != (width * height * 4) as usize.

Source

pub fn set_fog(&mut self, color: [f32; 3], near: f32, far: f32)

GPU.8 — set the fog blend. color is per-channel [0, 1]; near/far are world-space ray distances in voxel units. Hits with t < near show their full colour; hits with t > far show color exclusively; in between is a smoothstep blend.

Source

pub fn resize(&mut self, width: u32, height: u32)

Re-configure the swapchain to a new physical size. Call from WindowEvent::Resized. Drops the chunk-DDA storage texture so Self::render_chunk rebuilds it at the new size.

Source

pub fn render(&mut self)

GPU.1 render: single render pass clearing the swapchain to a slowly drifting colour, then presenting. Voxels arrive in GPU.3+.

Source

pub fn render_chunk( &mut self, resident: &GpuChunkResident, camera: &Camera, max_scan_dist: u32, )

GPU.3 single-chunk render. Dispatches chunk_dda.wgsl against resident’s storage buffers, then blits the low-res storage texture to the swapchain. camera.position is in chunk-local voxel units (host translates from world coords). max_scan_dist caps the per-pixel DDA loop — scene-demo wires + / - through this each frame.

§Panics

Internally expects the chunk-DDA resources to be built — they are constructed at the top of this function if missing. Cannot fire in normal control flow.

Source

pub fn render_grid( &mut self, grid: &GpuGridResident, camera: &Camera, max_outer_steps: u32, )

GPU.4 render — outer DDA over chunk indices + inner DDA into non-empty chunks. camera.position is in grid-local voxel units. max_outer_steps caps how many chunks the outer DDA may traverse per ray (scene-demo wires + / - through this).

§Panics

Internally expects the grid-DDA resources to be built; they are constructed at the top of this function if missing.

Source

pub fn render_scene( &mut self, scene: &GpuSceneResident, cameras: &[Camera], sprite_camera: &Camera, fov_y_rad: f32, max_outer_steps: u32, )

GPU.5 render — multi-grid scene marcher. cameras[i] is the world camera transformed into grid i’s local frame (caller-supplied; see scene-demo’s redraw_gpu for the glam-based transform). fov_y_rad is the shared vertical FOV; max_outer_steps caps per-ray chunk-DDA work for each grid.

§Panics

If cameras.len() != scene.grid_count or scene.grid_count > MAX_SCENE_GRIDS. cameras[i] is grid i’s world camera transformed into that grid’s local frame (the grid marcher works in grid-local space). sprite_camera is the world camera: instanced sprites carry world-space positions/transforms, so they must project through the untransformed world camera — not cameras[0], which is only the world camera when grid 0 is at identity.

Source

pub fn render_clear_deferred(&mut self)

Like Self::render (clear to colour) but deferred: stashes the frame for Self::present / [Self::paint_egui] instead of presenting. The facade uses this before any grid is resident so a HUD can still be painted over an empty scene.

Source

pub fn present(&mut self)

Present the frame stashed by the last deferred render (Self::render_scene / Self::render_clear_deferred). No-op if nothing is pending (e.g. the surface was lost mid-render).

Source

pub fn draw_lines_deferred(&mut self, cam: &GpuLineCamera, lines: &[GpuLine])

Draw depth-tested world-space GpuLines over the pending frame (L3.2). Projects each endpoint with cam (the marcher’s pinhole) + the last frame’s FOV / surface size, expands to screen-space quads, and runs a LoadOp::Load pass into the pending swapchain view — so the lines land on the marched frame and a later present / paint_egui still finishes it (the pending frame is left intact). Depth-tested lines are occluded by nearer marched geometry (compared against the scene-DDA depth buffer’s best_t); call after render, before present / paint_egui. No-op if no frame is pending.

Source

pub fn read_depth_pixel(&self, x: u32, y: u32) -> Option<f32>

Read back the per-pixel world-t depth at window pixel (x, y) from the last rendered frame, for screen→world picking. Returns the distance t along the (normalised) view ray to the nearest scene-grid surface, so the host reconstructs the world hit as cam.pos + t * normalize(ray_dir). None for out-of-bounds pixels, sky / no-hit (the T_INF sentinel), or when no scene frame has been rendered.

The depth buffer is the SCENE pass’s output (terrain + grids), untouched by the sprite pass (which reads it read-only), so a cursor sprite under the pointer does not occlude the pick.

Synchronous: copies the depth buffer to a mapped staging buffer and blocks on device.poll(Wait). Cheap enough for click-time picks; do not call it every frame.

Requires the last frame to have written depth, which happens when sprites are present (write_depth). The pick demo always has a cursor sprite, so this holds.

Compiles on wasm, but the wasm facade never calls it: WebGPU’s device.poll doesn’t block for the GPU, so the blocking recv() here would hang the single browser thread. Picking is deferred on the wasm GPU path (the facade returns None).

Source

pub fn pixel_ray( &self, right: [f64; 3], down: [f64; 3], forward: [f64; 3], x: f64, y: f64, ) -> Option<[f64; 3]>

World-space view-ray direction (un-normalised) for window pixel (x, y), under the GPU marcher’s projection — the canonical GPU unproject, mirroring scene_dda.wgsl’s render_scene (vertical-FOV pinhole). Uses the last-rendered frame’s target size + FOV; None before the first scene render. Pair with Self::read_depth_pixel for screen→world picking.

Source

pub fn set_sprite_instances( &mut self, registry: &SpriteModelRegistry, instances: &[SpriteInstance], )

GPU.10.1 — upload a sprite model registry + its instances for the DDA path. An empty instance slice clears all sprites.

Source

pub fn update_sprite_instance_transforms( &mut self, instances: &[SpriteInstance], )

Re-pose the already-resident sprite instances in place (no model volume re-upload) — the cheap per-frame path for animated KFA limbs. instances must match the last Self::set_sprite_instances in length + order. No-op if no sprite registry is resident.

Source

pub fn set_sprite_instance_colmul(&mut self, tables: &[[u64; 256]])

Set the per-instance kv6colmul[256] lighting tables (voxlap’s update_reflects output, e.g. via roxlap_core::sprite:: sprite_colmul), in the same order/length as the last Self::set_sprite_instances. The GPU sprite pass modulates each voxel by its surface normal’s entry — matching the CPU rasteriser. No-op if no sprite registry is resident.

Source

pub fn set_sprite_lod_px(&mut self, px: f32)

GPU.10.4 — set the LOD pixel threshold: a sprite steps to the next mip once a mip-0 voxel would project below px screen pixels. 1.0 is the natural “no sub-pixel voxels” default; larger values force LOD in closer (useful for inspection). Clamped to ≥ 0.25.

Source

pub fn set_scene_mip_scan_dist(&mut self, dist: f32)

GPU.11.1 — set the scene-grid LOD scan distance (world units). A chunk entered at world-t t is marched at mip floor(log2(max(t, msd) / msd)), clamped to its grid’s mip ladder. 0 disables LOD (always mip-0). Larger values push the coarser mips farther out — the axis-aligned-mip-beams mitigation lever (GPU.11.2). Default 64 (matches CPU mip_scan_dist).

Source

pub fn set_scene_side_shades(&mut self, s: [i8; 6])

Set per-face grid side-shading — voxlap’s setsideshades(top, bot, left, right, up, down). Each value is subtracted (as a u8, matching the CPU gcsub high byte) from a hit voxel’s brightness byte before shading, so the scene-DDA pass darkens grid faces the same way the CPU rasteriser does. [0; 6] disables it (the default). The hit face is taken from the DDA’s last-stepped axis + ray direction.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,