Core Engine

aether-renderer

Rendering pipeline with GPU scheduling and foveated rendering

The aether-renderer crate provides Aether's rendering pipeline, including GPU frame scheduling, foveated rendering for VR, level-of-detail management, progressive mesh streaming, and a software rasterizer for prototyping.

Overview

The renderer is designed around a frame budget model that adapts to runtime conditions. Each frame, the scheduler evaluates GPU load, headset tracking data, and scene complexity to decide how to allocate rendering work. Key capabilities include:

  • Frame budgeting with configurable target frame rates and automatic quality scaling.
  • Foveated rendering that reduces peripheral detail based on eye-tracking data, saving GPU cycles where visual acuity is lowest.
  • LOD policies for automatic level-of-detail selection based on distance and screen coverage.
  • Progressive mesh streaming that loads geometry incrementally as the viewer approaches.
  • Stereo rendering with configurable inter-pupillary distance and asymmetric projection.

Key Types

FrameScheduler

Manages per-frame GPU workload distribution. Evaluates load buckets and decides the frame mode (full, reduced, or skip) based on the current budget.

use aether_renderer::{FrameScheduler, FrameBudget, FrameMode};

let budget = FrameBudget {
    target_fps: 90,
    max_frame_time_ms: 11.0,
};
let scheduler = FrameScheduler::new(budget);

FrameMode

An enum describing how the current frame should be rendered, determined by the scheduler.

use aether_renderer::{decide_frame_mode, FrameModeInput};

let input = FrameModeInput {
    gpu_utilization: 0.85,
    frame_time_ms: 10.2,
    foveation_active: true,
};
let mode = decide_frame_mode(&input);

FoveationConfig

Controls foveated rendering parameters. Higher tiers reduce peripheral resolution more aggressively.

use aether_renderer::{FoveationConfig, FoveationTier};

let config = FoveationConfig {
    tier: FoveationTier::Medium,
    inner_radius: 0.3,
    outer_radius: 0.8,
};

LODPolicy

Defines how level-of-detail transitions occur based on camera distance and screen coverage thresholds.

use aether_renderer::{LODPolicy, LODLevel, LodCurve};

let policy = LODPolicy {
    curve: LodCurve::Linear,
    levels: vec![
        LODLevel { distance: 10.0, detail: 1.0 },
        LODLevel { distance: 50.0, detail: 0.5 },
        LODLevel { distance: 100.0, detail: 0.2 },
    ],
};

ProgressiveMeshStreaming

Handles incremental geometry loading. Meshes are streamed in progressively finer detail as the camera moves closer.

use aether_renderer::{ProgressiveMeshStreaming, StreamRequest, StreamPriority};

let mut streaming = ProgressiveMeshStreaming::new();
streaming.request(StreamRequest {
    asset_id: mesh_id,
    priority: StreamPriority::High,
    target_lod: 0,
});

RenderBackend

Trait abstracting the GPU backend. Implementations exist for wgpu-based hardware rendering and a software rasterizer used for testing and prototyping.

use aether_renderer::{RenderBackend, FrameRuntimeConfig, FrameRuntimeInput};

// The runtime selects a backend based on platform capabilities
let config = FrameRuntimeConfig::default();

Usage Examples

A typical frame loop integrates the scheduler with the render backend:

use aether_renderer::{
    FrameScheduler, FrameBudget, FrameWorkload, StereoConfig,
};

let budget = FrameBudget {
    target_fps: 90,
    max_frame_time_ms: 11.0,
};
let mut scheduler = FrameScheduler::new(budget);

let stereo = StereoConfig {
    ipd_mm: 63.0,
    asymmetric_fov: true,
};

// Each tick, submit workloads and let the scheduler decide quality
let workload = FrameWorkload {
    draw_calls: 1200,
    triangle_count: 850_000,
    texture_memory_mb: 256,
};

Batch Rendering

The batching module groups draw calls by material to minimize GPU state changes:

use aether_renderer::{BatchRequest, MaterialBatchKey, BatchHint};

let batch = BatchRequest {
    key: MaterialBatchKey::new(shader_id, texture_id),
    hint: BatchHint::Opaque,
    instance_count: 50,
};