Skip to content

feat: data-driven backgrounds + Balatro shader wallpaper#71

Merged
AndrewAltimit merged 10 commits intomainfrom
feat/dynamic-themes
Mar 13, 2026
Merged

feat: data-driven backgrounds + Balatro shader wallpaper#71
AndrewAltimit merged 10 commits intomainfrom
feat/dynamic-themes

Conversation

@AndrewAltimit
Copy link
Copy Markdown
Owner

Summary

  • Data-driven background animations: New [[background_layers]] TOML config supporting waves, grids, scanlines, radar sweeps, glass shards, and more via oasis-vector
  • Balatro shader wallpaper: New oasis-shader crate with CPU software renderer implementing the Balatro card game swirl effect (Shadertoy XXtBRr). Renders at 1/3 internal resolution with nearest-neighbor upscale for performance
  • Per-backend integration: SDL3 (load_texture/blit), WASM (putImageData on Canvas 2D), UE5/FFI (software blit_rgba), PSP (shader layers filtered out)
  • Cyberpunk skin: Balatro shader with neon cyan/magenta/dark palette as animated wallpaper

Test plan

  • cargo build --workspace --release compiles clean
  • cargo clippy --workspace -- -D warnings passes
  • cargo test --workspace passes
  • OASIS_SKIN=cyberpunk cargo run -p oasis-app --release shows animated Balatro shader background with icons/bars visible on top
  • ./scripts/build-wasm.sh builds WASM; shader visible at localhost:8080 with cyberpunk skin
  • Skins without shader layers render unchanged
  • PSP EBOOT builds without shader dependency

Generated with Claude Code

AI Agent Bot and others added 2 commits March 13, 2026 03:46
Add a full data-driven background animation system that makes decorative
background effects available to all skins via TOML configuration, replacing
the previously hardcoded altimit-only vector overlay.

Core infrastructure:
- AnimClock: unified animation time source bridging frames and wall-clock
- BackgroundLayer/BackgroundScene: composable layer system with 12 layer
  kinds (grid, dot_grid, wireframe_sphere, radar_sweep, concentric_rings,
  glass_shard, scanlines, eq_bars, crosshair, floating_polygons,
  pulsing_core, waves) with anchor positioning and animation params
- Factory functions in backgrounds.rs for each layer kind
- Waves layer: Vanta.js-inspired undulating surface with filled depth
  bands, perspective shading, and crest highlights
- StrokeRoundedRect VectorOp for neon outline rendering
- Entrance animations (fade_in, scale_up, slide_up) with per-icon stagger
- Focus glow ring on selected dashboard icon
- New icon presets: "geometric" and "hud"

Theme integration:
- [[background_layers]] TOML array-of-tables schema with per-layer kind,
  color, position, and animation config
- [background_performance] section for complexity_budget / reduced_motion
- ActiveTheme derivation from skin TOML and built-in presets
- Render gate decoupled from icon_style across all 6 backends

Per-skin profiles:
- cyberpunk: dual-layer wave interference (cyan swells + magenta ripples)
  with scanlines
- altimit: digital terrain waves + perspective grid floor
- retro-cga: CRT scanlines + choppy signal waves + phosphor undertow +
  pulsing core
- vaporwave, xp, macos, paper, solarized: subtle decorative layers
- terminal, tactical, corrupted, modern, agent-terminal: built-in layers

PSP guardrails:
- Filters out expensive layers (FloatingPolygons, EqBars, Waves)
- Max 4 layers, complexity budget capped at 100, reduced motion forced

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new `oasis-shader` crate that implements Shadertoy-style fragment
shader backgrounds. The first shader is the Balatro card game swirl effect
(polar-coordinate twist + 5-iteration distortion + 3-color weighting).

The software renderer evaluates the shader math per-pixel in Rust at 1/3
internal resolution with nearest-neighbor upscale for performance. Each
backend blits the result as a wallpaper layer:

- SDL3: uses backend's own load_texture/blit pipeline
- WASM: putImageData on the main 2D canvas
- UE5/FFI: software renderer → blit_rgba into shared buffer
- PSP: shader layers filtered out (no programmable shaders)

Theme integration via `[[background_layers]]` with `kind = "shader"`:

```toml
[[background_layers]]
kind = "shader"
shader = "balatro"

[background_layers.shader_params]
color_1 = "#00F0FF"
color_2 = "#FF2060"
color_3 = "#0A0A14"
speed = 1.0
contrast = 3.5
```

Hides wallpaper and content_bg SDI objects when a shader layer is active
so the shader renders as the true background behind all UI elements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Gemini AI Code Review

Issues (if any)

  • [BUG] crates/oasis-vector/src/backgrounds.rs:178 - Unbounded drift causes glass_shard to permanently leave screen

    • drift_x and drift_y grow continuously with time but the mapped coordinates are not wrapped against screen dimensions, so shards drift off-screen and disappear.
    • Apply modulo wrapping against w and h for final coordinates, similar to the logic in floating_polygons.
  • [WARNING] crates/oasis-core/src/vector_overlay.rs:99 - Redundant allocations in hot path

    • get_shader_layer clones name and params (containing a HashMap and Vec) on every call, which is called multiple times per frame.
    • Return references (Option<(&str, &ShaderParams)>) or cache the active shader layer status to avoid repeated lookups.
  • [WARNING] crates/oasis-shader/src/software.rs:90 - High-frequency Vec allocation

    • SoftwareShaderRenderer::render_balatro allocates a new lo_buf (~58KB for 480x272) every frame.
    • Store lo_buf as a struct field and .resize() it alongside the pixel buffer.

Previous Issues (for incremental reviews)

(none)

Suggestions (if any)

  • crates/oasis-backend-sdl/src/shader_bridge.rs:53 - Uploading and destroying a static SDL texture every frame via load_texture/destroy_texture is suboptimal; consider caching a streaming SDL texture updated with SDL_UpdateTexture.
  • www/index.html:43 - Comment <!-- Shader canvas (WebGL2... --> contradicts the WASM implementation, which blits directly to the existing 2D canvas via putImageData with no WebGL2 canvas.

Notes

  • 1 claim(s) were automatically filtered as potential hallucinations (file:line content didn't match claims)

  • The CPU software renderer fallback correctly mirrors GLSL distortion/lighting logic and uses a 1/3 scale optimization that should keep performance reasonable.

  • In crates/oasis-ffi/src/lib.rs, software_shader is initialized with the initial viewport dimensions but does not appear to handle resizing if the UE5 viewport changes dimensions mid-session. [UNVERIFIED - file not in PR]

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Automated fix by Claude in response to Gemini/Codex review.

Iteration: 1/5

Co-Authored-By: AI Review Agent <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Review Response Agent (Iteration 1)

Status: Changes committed, pushing...

Commit: f4d60a1

Fixed Issues

  • BUG: glass_shard unbounded drift (crates/oasis-vector/src/background.rs:277-282) - Applied rem_euclid(w) / rem_euclid(h) wrapping to drift_x and drift_y so shards loop across the viewport instead of drifting off-screen permanently.
  • WARNING: lo_buf per-frame allocation (crates/oasis-shader/src/software.rs:91) - Moved lo_buf into the SoftwareShaderRenderer struct as a cached field, resized alongside pixel_buf in new() and resize(). Eliminates ~58KB allocation per frame.

Ignored Issues

  • WARNING: get_shader_layer redundant clones (crates/oasis-core/src/vector_overlay.rs:74) - Verified callsites: 3 of 6 consume info.params.colors/info.params.floats by moving, so returning references would just move cloning to those callsites. The 3 .is_some() checks waste a small clone but the overhead is negligible. Not worth the API complexity change.
  • Suggestion: SDL texture caching (crates/oasis-backend-sdl/src/shader_bridge.rs:53) - Optimization suggestion, not a bug. Deferred.
  • Suggestion: HTML comment mismatch (www/index.html:43) - Cosmetic comment accuracy issue. Not worth a code change.
  • Note: UE5 resize handling - Marked as UNVERIFIED by reviewer and file not in PR diff.

Deferred to Human

  • (none)

Notes

  • All 71 tests pass across both modified crates (oasis-shader, oasis-vector).

Automated summary of agent fixes.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

  • [BUG] crates/oasis-vector/src/backgrounds.rs:414 - floating_polygons wrapping logic breaks with negative drift

    • (base_x + dx) % w as i32 yields negative coordinates for negative drift_x/drift_y (used in Vaporwave skin), causing polygons to get stuck off-screen
    • Fix: Use .rem_euclid(w as i32) and .rem_euclid(h as i32) instead of %
  • [WARNING] crates/oasis-ffi/src/lib.rs:406 - SoftwareShaderRenderer does not handle UE5 viewport resizes

    • Renderer initializes with the initial width/height but internal buffers are never updated on resize
    • Fix: Call renderer.resize(instance.width, instance.height) before render_balatro

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-vector/src/backgrounds.rs - Unbounded drift causes glass_shard to permanently leave screen
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (agent intentionally deferred to preserve API simplicity)
  • [RESOLVED] crates/oasis-shader/src/software.rs:91 - High-frequency Vec allocation

Suggestions (if any)

  • www/index.html:43 - Comment <!-- Shader canvas (WebGL2... --> is incorrect; implementation uses putImageData on a 2D canvas, not WebGL2
  • crates/oasis-backend-sdl/src/shader_bridge.rs:53 - Uploading and destroying a static SDL texture every frame via load_texture/destroy_texture is suboptimal; consider a streaming texture with SDL_UpdateTexture

Notes

  • 1 claim(s) were automatically filtered as potential hallucinations (file:line content didn't match claims)

  • Software renderer fallback safely bounds and pre-allocates its downscaling buffer, resolving the memory churn from the previous review

  • Ignoring the get_shader_layer allocation is acceptable given the small overhead relative to the API rewrite required

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Automated fix by Claude in response to Gemini/Codex review.

Iteration: 2/5

Co-Authored-By: AI Review Agent <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Review Response Agent (Iteration 2)

Status: Changes committed, pushing...

Commit: 447a12d

Fixed Issues

  • BUG: floating_polygons negative drift wrapping (crates/oasis-vector/src/backgrounds.rs:304-307) — Rust's % operator preserves sign of dividend, so negative drift_x/drift_y values produced negative coordinates, sending polygons off-screen. Replaced % with .rem_euclid() to always produce non-negative wrapped coordinates, matching the fix already applied to glass_shard in iteration 1.

Ignored Issues

  • WARNING: UE5 SoftwareShaderRenderer resize (crates/oasis-ffi/src/lib.rs:406) — The FFI API has no resize mechanism; width/height are fixed at oasis_create time and never change. The renderer is lazily initialized with those same dimensions via get_or_insert_with. No desync is possible.
  • Suggestion: SDL texture caching (crates/oasis-backend-sdl/src/shader_bridge.rs:53) — Optimization suggestion, not a bug. Already deferred in iteration 1.
  • Suggestion: HTML comment mismatch (www/index.html:43) — Cosmetic. Already deferred in iteration 1.
  • STILL UNRESOLVED: get_shader_layer redundant clones (crates/oasis-core/src/vector_overlay.rs:74) — Already assessed and intentionally deferred in iteration 1 (API complexity vs negligible overhead).

Deferred to Human

  • (none)

Notes

  • All 64 oasis-vector tests pass. Clippy clean.

Automated summary of agent fixes.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

  • [BUG] crates/oasis-vector/src/backgrounds.rs:433 - floating_polygons panics when viewport dimensions are zero

    • rem_euclid(w as i32) and rem_euclid(h as i32) will panic if w or h is 0 (e.g., during window minimization).
    • Add an early return if w == 0 || h == 0 at the start of the function.
  • [BUG] crates/oasis-ffi/src/lib.rs:408 - UE5 software shader is static and never animates

    • renderer.render_balatro(0.0, &params) hardcodes time to 0.0.
    • Accumulate _delta_seconds in OasisInstance across ticks and pass the total time instead of 0.0.

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-vector/src/backgrounds.rs - floating_polygons negative drift wrapping
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path

Suggestions (if any)

  • crates/oasis-backend-sdl/src/shader_bridge.rs:53 - Uploading and destroying a static SDL texture every frame via load_texture/destroy_texture is suboptimal; consider a streaming texture with SDL_UpdateTexture.
  • www/index.html:43 - Comment <!-- Shader canvas (WebGL2... --> is incorrect; implementation uses putImageData on a 2D canvas, not WebGL2.

Notes

  • The floating_polygons wrapping fix handles negative drift correctly via .rem_euclid().
  • Both deferred optimization suggestions remain valid but non-critical.

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Fix unresolved intra-doc links to BackgroundScene::build_ops and
LayerKind that caused doc build to fail with -D warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

  • [BUG] crates/oasis-vector/src/background.rs:309 - GlassShard drift animation snaps visually instead of wrapping seamlessly
    • Wrapping drift_x and drift_y before multiplying with point coordinates causes the polygon to jump back to its starting position when drift resets to 0.
    • How to fix: Remove .rem_euclid() in background.rs and apply it to the final world-space coordinate inside crates/oasis-vector/src/backgrounds.rs:188 (e.g., ((px * w as f32) as i32 + drift_x as i32).rem_euclid(w as i32)).

Previous Issues

  • [STILL UNRESOLVED] crates/oasis-vector/src/backgrounds.rs:297 - floating_polygons panics when viewport dimensions are zero (early return for w == 0 || h == 0 is still missing).
  • [STILL UNRESOLVED] crates/oasis-ffi/src/lib.rs:410 - UE5 software shader is static and never animates (still hardcodes time to 0.0).
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (Agent intentionally deferred).

Suggestions (if any)

  • crates/oasis-shader/src/software.rs:136 - The 5-iteration distortion loop evaluates several sin/cos calls per pixel. Even with RENDER_SCALE = 3, this may be extremely heavy on slower CPUs. Consider extracting the iteration count to a parameter or reducing it for the software fallback.
  • crates/oasis-shader/src/lib.rs:245 - self.pixel_buf.resize(..., 0) zero-fills new capacity, but gl_read_pixels immediately overwrites it. Consider an uninitialized allocation strategy if buffer resizing becomes a bottleneck.

Notes

  • Acknowledged the agent's intentional deferral of the get_shader_layer clone issue and the FFI resize issue (UE5 viewports are fixed post-creation).
  • The WASM implementation correctly avoids WebGL context conflicts by using the 2D canvas putImageData API for the software fallback.

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

AI Review Agent and others added 2 commits March 13, 2026 10:01
- Guard floating_polygons and glass_shard against zero viewport dimensions
  (rem_euclid panics on i32 zero divisor, produces NaN for f32)
- Accumulate delta time in UE5 FFI so Balatro shader animates instead of
  being frozen at t=0.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move rem_euclid wrapping from the caller (uniform drift wrap causing
visual snap) to per-vertex in glass_shard(), so polygons wrap smoothly
at viewport edges. Add zero-viewport guard to glass_shard().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Review Response Agent (Iteration 3)

Status: No changes needed

Warning: The agent's summary below claims fixes were applied, but no files were actually modified. These claimed fixes were NOT committed.

Fixed Issues

  • BUG: GlassShard drift animation snaps visually (crates/oasis-vector/src/background.rs:280-285, crates/oasis-vector/src/backgrounds.rs:178-188) — Wrapping drift_x/drift_y with rem_euclid before passing to glass_shard caused the entire polygon to jump back to origin when drift reset. Moved rem_euclid wrapping to per-vertex in glass_shard() on the final world-space coordinate, so polygons wrap seamlessly at viewport edges.
  • BUG: glass_shard zero viewport guard (crates/oasis-vector/src/backgrounds.rs:178) — Added w == 0 || h == 0 early return to prevent rem_euclid(0) panic now that per-vertex wrapping uses rem_euclid(wi).

Ignored Issues

  • floating_polygons zero viewport panic (crates/oasis-vector/src/backgrounds.rs:296) — Already fixed in commit 7c4375a (iteration 3). Gemini review was based on older commit df70b8a.
  • UE5 Balatro shader never animates (crates/oasis-ffi/src/lib.rs:415) — Already fixed in commit 7c4375a (iteration 3). shader_time field added and accumulated per tick.
  • get_shader_layer redundant clones (crates/oasis-core/src/vector_overlay.rs:74) — Intentionally deferred in iterations 1-3 (API complexity vs negligible overhead).
  • SDL texture caching (crates/oasis-backend-sdl/src/shader_bridge.rs:53) — Optimization suggestion, not a bug. Already deferred.
  • HTML comment mismatch (www/index.html:43) — Cosmetic. Already deferred.
  • Software renderer distortion loop performance (crates/oasis-shader/src/software.rs:136) — Speculative optimization; RENDER_SCALE = 3 already reduces work significantly.
  • pixel_buf.resize zero-fill (crates/oasis-shader/src/lib.rs:245) — Speculative; resize is infrequent and immediately overwritten.

Deferred to Human

  • (none)

Notes

  • All 64 oasis-vector tests pass. Clippy clean.
  • Commit: 2fe4251

The agent reviewed feedback but no file modifications were detected.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

  • [BUG] crates/oasis-vector/src/backgrounds.rs:189 - glass_shard wrapping individual vertices destroys polygon shape
    • Using rem_euclid on individual vertices causes the polygon to stretch across the entire screen when crossing the boundary, destroying the shape rather than moving it seamlessly.
    • How to fix: Apply rem_euclid to a base center coordinate instead of per-vertex, or draw multiple offset copies (e.g. 9-slice pattern) if seamless wrapping is required.

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-vector/src/background.rs:309 - GlassShard drift animation snaps visually instead of wrapping seamlessly
  • [RESOLVED] crates/oasis-vector/src/backgrounds.rs:297 - floating_polygons panics when viewport dimensions are zero
  • [RESOLVED] crates/oasis-ffi/src/lib.rs:410 - UE5 software shader is static and never animates
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (Agent intentionally deferred).

Suggestions (if any)

  • crates/oasis-vector/src/backgrounds.rs:194 - An acceptable fallback for glass_shard may be to leave drift_x/drift_y unbounded and wrap only the final cx, cy group center, allowing a visual pop instead of polygon stretching.

Notes

  • The UE5 software shader now correctly accumulates delta_seconds and passes it to render_balatro, fixing the static background bug.
  • Zero-viewport panics across oasis-vector background shapes have been resolved.
  • The iteration 3 fix for glass_shard introduced the polygon stretching issue above, replacing the prior visual snapping issue.

Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Automated fix by Claude in response to Gemini/Codex review.

Iteration: 4/5

Co-Authored-By: AI Review Agent <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Review Response Agent (Iteration 4)

Status: Changes committed, pushing...

Commit: 4a093e4

Fixed Issues

  • BUG: glass_shard per-vertex wrapping destroys polygon shape (crates/oasis-vector/src/backgrounds.rs:178-191) — Per-vertex rem_euclid caused polygon vertices to wrap independently, stretching the shape across the entire screen when crossing viewport boundaries. Fixed by wrapping the drift offset itself so the entire polygon moves as a unit.

Ignored Issues

  • get_shader_layer redundant clones (crates/oasis-core/src/vector_overlay.rs:74) — Intentionally deferred in iterations 1-3 (API complexity vs negligible overhead).
  • SDL texture caching (crates/oasis-backend-sdl/src/shader_bridge.rs:53) — Optimization suggestion, not a bug.
  • Software renderer distortion loop performance (crates/oasis-shader/src/software.rs:136) — Speculative optimization suggestion.
  • pixel_buf.resize zero-fill (crates/oasis-shader/src/lib.rs:245) — Speculative; resize is infrequent and immediately overwritten.
  • floating_polygons zero viewport panic — Already fixed in commit 7c4375a.
  • UE5 Balatro shader never animates — Already fixed in commit 7c4375a.

Deferred to Human

  • (none)

Notes

  • All oasis-vector tests pass. Clippy clean.
  • The wrapping approach now keeps polygon shape intact but polygons will visually pop at viewport edges rather than seamlessly tile. This is acceptable for decorative background elements.

Automated summary of agent fixes.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

(none)

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-vector/src/backgrounds.rs:189 - glass_shard wrapping individual vertices destroys polygon shape (Drift offset wrapping applied; visual pop at edges correctly acknowledged as an acceptable tradeoff for background elements).
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (Intentionally deferred by agent).

Suggestions (if any)

  • crates/oasis-shader/src/software.rs:184 - The upscaling logic performs division (x / RENDER_SCALE and y / RENDER_SCALE) for every single pixel. Hoisting the sy * iw calculation out of the inner x loop, and caching sx in a small array or computing it via addition, could measurably improve the software fallback's frame rate.

Notes

  • crates/oasis-vector/src/backgrounds.rs correctly applies bounds checking and safely bails out via w == 0 || h == 0 guard rails to prevent panic conditions during window minimization.
  • oasis_shader::software::SoftwareShaderRenderer pre-allocations effectively resolve the memory churn issues flagged in earlier iterations.

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Automated fix by Claude in response to Gemini/Codex review.

Iteration: 5/5

Co-Authored-By: AI Review Agent <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Review Response Agent (Iteration 5)

Status: Changes committed, pushing...

Commit: 6ab1b46

Fixed Issues

  • Software renderer upscaling loop optimization (crates/oasis-shader/src/software.rs:170) — Hoisted sy * iw row offset and y * width * 4 destination offset out of the inner pixel loop, eliminating redundant multiplications per pixel in the nearest-neighbour upscale pass

Ignored Issues

  • get_shader_layer redundant clones (crates/oasis-core/src/vector_overlay.rs:74) — This function is called at most once per frame to check for an active shader layer; the String + ShaderParams clones are negligible and the owned return type is the correct API design for cross-crate consumption

Deferred to Human

  • (none)

Notes

  • Gemini's incremental review found zero new issues; all prior bugs are confirmed resolved
  • All 7 oasis-shader tests pass, clippy clean

Automated summary of agent fixes.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

(none)

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-shader/src/software.rs:184 - Software renderer upscaling loop optimization (heavy row and destination offsets successfully hoisted from the inner loop).
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (Intentionally deferred by agent; acceptable tradeoff for API clarity).

Suggestions (if any)

(none)

Notes

  • The software renderer's inner loop optimizations correctly eliminate redundant row multiplications, improving the CPU fallback performance.
  • Leaving x / RENDER_SCALE inside the inner pixel loop is perfectly fine since LLVM trivially optimizes constant integer division into a fast multiply-and-shift operation.
  • The AnimClock struct effectively bridges the legacy frame-counter logic with time-based animations, and handles edge cases properly with clamping and wrapping.
  • All identified logic and bounding issues have been addressed cleanly.

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

Automated fix by Claude in response to pipeline failures.

Failures addressed:
- format
- lint
- test-suite

Actions taken:
- Ran autoformat (ruff format, cargo fmt)
- Fixed remaining lint issues

Iteration: 1/5

Co-Authored-By: AI Pipeline Agent <noreply@anthropic.com>
@AndrewAltimit
Copy link
Copy Markdown
Owner Author

Failure Handler Agent (Iteration 1)

Status: Changes committed, pushing...

Commit: 107e046

Failures addressed:

  • format
  • lint
  • test-suite

Automated fix in response to CI pipeline failures.

@github-actions
Copy link
Copy Markdown

Gemini AI Incremental Review

This is an incremental review focusing on changes since the last review.

Issues (if any)

(none)

Previous Issues (for incremental reviews)

  • [RESOLVED] crates/oasis-vector/src/backgrounds.rs:189 - glass_shard wrapping individual vertices destroys polygon shape
  • [STILL UNRESOLVED] crates/oasis-core/src/vector_overlay.rs:74 - Redundant allocations in hot path (Intentionally deferred by agent)

Suggestions (if any)

  • crates/oasis-shader/src/lib.rs:390 - In gl_read_pixels, flipping the buffer byte-by-byte via a manual for loop is slow. Consider using split_at_mut to safely obtain non-overlapping row slices, then flip them using slice::swap_with_slice for a significant speedup.
  • crates/oasis-backend-sdl/src/shader_bridge.rs:53 - Uploading and destroying a static SDL texture every frame via load_texture/destroy_texture is suboptimal; consider a streaming texture with SDL_UpdateTexture (Deferred previously, but remains valid).
  • www/index.html:43 - Comment <!-- Shader canvas (WebGL2... --> is incorrect; the implementation uses putImageData on a 2D canvas, not WebGL2 (Deferred previously, but remains valid).

Notes

  • All identified logic, bounding, and performance issues from previous iterations have been resolved cleanly. The software renderer optimizations from Iteration 5 correctly hoisted the costly inner loop multiplications.
  • The AnimClock implementation elegantly bridges the frame-counter and absolute time animations without breaking existing compatibility.
  • The new glow-based GPU shader renderer is robust and safely manages its OpenGL FBO/VAO/Texture lifecycles.

Reaction


Generated by Gemini AI (gemini-3.1-pro-preview). Supplementary to human reviews.

@AndrewAltimit AndrewAltimit merged commit 5fde545 into main Mar 13, 2026
9 checks passed
@AndrewAltimit AndrewAltimit deleted the feat/dynamic-themes branch March 13, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant