-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
← Home
A contributor on-ramp. Closes the page knowing where each piece of Solarxy lives in the seven-crate workspace, how the render pipeline composes, and which file to open when adding a feature in a given area.
For the deepest patterns - GPU uniform alignment discipline, MSAA boundary
nuances, the IBL update chokepoint, dock layout serde compatibility
caveats - see the in-repo
CLAUDE.md.
This page is the structural orientation; that file is the deeper code-side
reference, maintained alongside the code.
- The seven crates
- Dependency DAG
- The render pipeline
- State flow
- Dock layout persistence
- The validation library boundary
- Where to look for X
Solarxy is a workspace of seven crates. The GPU-free crates (solarxy-core,
solarxy-formats) sit at the bottom; the GPU-bound and UI-bound crates
layer on top. This boundary lets the CLI link the analyzer without pulling
wgpu, winit, or egui.
| Crate | What it owns |
|---|---|
solarxy (root) |
Thin GUI entrypoint binary. Parses GuiArgs, sets up tracing, loads preferences, calls solarxy_app::run_viewer. |
solarxy-core |
Pure CPU types: geometry primitives, validation logic, preferences I/O, view-config enums, JSON / report shapes, review sidecar. No GPU. |
solarxy-formats |
Format loaders (OBJ, STL, PLY, glTF / GLB) returning RawModelData. Integration tests live alongside under tests/loaders.rs. |
solarxy-renderer |
All wgpu state - pipelines, bind groups, shaders, IBL, SSAO, bloom, shadow, composite, camera, per-frame draw orchestration. |
solarxy-app |
winit + egui application shell. Owns State, input routing, sidebar, menu bar, dock, console. |
solarxy-cli |
clap-driven CLI + ratatui Analyze TUI + the analyzer + the optional self-updater. |
solarxy-validate |
Batch validation orchestration + CI pipeline adapters (GitHub Actions, generic-JSON). Library API consumed by solarxy-cli and by external vendors. |
The version is single-sourced in [workspace.package] and inherited by
every crate via version.workspace = true.
The seven crates form an acyclic dependency graph. No crate depends
upward; solarxy-core and solarxy-formats are pure data / algo
utilities.
flowchart BT
classDef base fill:#1F2430,stroke:#5C6773,color:#CCCAC2
classDef mid fill:#1F2430,stroke:#78A0EE,color:#78A0EE
classDef top fill:#1F2430,stroke:#FFC44C,color:#FFC44C
core[solarxy-core<br/>CPU types, validation]:::base
formats[solarxy-formats<br/>OBJ STL PLY glTF loaders]:::base
renderer[solarxy-renderer<br/>wgpu pipelines, shaders]:::mid
validate[solarxy-validate<br/>batch + CI adapters]:::mid
app[solarxy-app<br/>winit + egui shell]:::mid
cli[solarxy-cli<br/>clap + TUI + updater]:::top
root[solarxy root<br/>GUI entrypoint]:::top
formats --> core
renderer --> core
renderer --> formats
validate --> core
validate --> formats
app --> core
app --> formats
app --> renderer
cli --> core
cli --> formats
cli --> validate
root --> core
root --> app
Foundation crates at the bottom, GPU- and UI-bound layers on top. solarxy-core and solarxy-formats carry no GPU dependencies so the CLI can link them without pulling wgpu, winit, or egui.
The acyclic shape is what lets solarxy-cli ship without wgpu, winit, or
egui dependencies. The CLI's analyzer feature gate pulls in
solarxy-formats and solarxy-validate only when analyze mode is needed.
flowchart LR
classDef stage fill:#1F2430,stroke:#5C6773,color:#CCCAC2
classDef msaa fill:#1F2430,stroke:#FFC44C,color:#FFC44C
classDef post fill:#1F2430,stroke:#78A0EE,color:#78A0EE
classDef ui fill:#1F2430,stroke:#7FD962,color:#7FD962
classDef gate fill:#33415E,stroke:#FFC44C,color:#FFC44C
s1[1. Shadow pass]:::stage --> s2[2. GBuffer<br/>if SSAO on]:::stage
s2 --> s3[3. Background]:::msaa
s3 --> s4[4. Main pass<br/>PBR + Inspection]:::msaa
s4 --> s5[5. Wireframe<br/>overlays]:::msaa
s5 --> s6[6. Visualization<br/>overlays]:::msaa
s6 --> R{MSAA resolve}:::gate
R --> s7[7. SSAO]:::post
R --> s8[8. Bloom]:::post
s7 --> s9[9. Composite<br/>+ tone map]:::post
s8 --> s9
s9 --> s10[10. egui overlay<br/>+ review markers]:::ui
Stages 3-6 run inside the MSAA main pass; resolve happens before SSAO and Bloom read the HDR target. Review markers draw in the egui overlay after composite, so they never z-fight with post-processing.
Per pane, per frame, ten ordered stages. The top-level orchestration lives
in
crates/solarxy-renderer/src/frame.rs;
the per-pane app-side call sequencing lives in
crates/solarxy-app/src/state/render.rs.
-
Shadow pass - depth from the key light
(
shaders/shadow.wgsl). -
GBuffer pass - position + normal buffers
(
shaders/gbuffer.wgsl), only when SSAO is on. -
Background - gradient or HDRI sky
(
shaders/background.wgsl/skybox.wgsl). -
Main pass - PBR with inspection-mode switch
(
shaders/shader.wgsl). -
Wireframe overlays - inside the MSAA main pass
(
shaders/edge_wire.wgsl,ghosted.wgsl). -
Visualization overlays - grid, normals, axes, bounds, validation
highlights
(
grid.wgsl,normals.wgsl,gizmo.wgsl,validation.wgsl). -
SSAO post-process - reads the resolved HDR target
(
ssao.wgsl,ssao_blur.wgsl). -
Bloom post-process - reads the resolved HDR target
(
bloom.wgsl). -
Composite - tone mapping + viewport scissor
(
composite.wgsl). - egui overlay - menu bar, panels, status bar, and review markers (drawn as egui shapes, after composite, so they are never z-fought by post-processing).
UV-Map panes follow a parallel path through
uv_map.wgsl,
uv_debug.wgsl,
and
uv_overlap.wgsl;
they skip SSAO and Bloom and do not participate in the review-marker
overlay.
The central app struct is State, defined in
crates/solarxy-app/src/state/mod.rs.
It owns:
- The viewport panes (
compute_panes, the layout math for F1-F5). - The camera rig (one per pane, all sharing the same orbit interface).
- The loaded model's GPU scene (
ModelSceneinscene.rs). - The input handler (keyboard, mouse, dialogs, menu actions; lives under
state/input/). - The Review System state - the in-memory mirror of the current
.solarxy-review.json(state/review.rs). - The display, rendering, and lighting view config.
Sidebar <-> state synchronization goes through GuiSnapshot in
crates/solarxy-app/src/gui/snapshot.rs.
Adding a sidebar control means adding a field to GuiSnapshot and wiring
both from_state (read) and the matching write_back_* (write).
flowchart LR
classDef auto fill:#1F2430,stroke:#78A0EE,color:#78A0EE
classDef manual fill:#1F2430,stroke:#FFC44C,color:#FFC44C
classDef def fill:#1F2430,stroke:#5C6773,color:#CCCAC2
classDef active fill:#33415E,stroke:#FFC44C,color:#FFC44C
DEF[default_dock_state]:::def
LAST[last_layout_json<br/>auto, on quit]:::auto
SAVED[saved_layout_json<br/>manual, Save Layout]:::manual
ACTIVE[Active layout<br/>in memory]:::active
DEF -->|first launch| ACTIVE
LAST -->|next launch restore| ACTIVE
ACTIVE -->|on quit| LAST
ACTIVE -->|Save Layout| SAVED
SAVED -->|Restore Saved Layout| ACTIVE
ACTIVE -->|Reset Layout to Default| DEF
Three persisted layout states and the three menu actions that move between them. Reset Layout never overwrites a saved blob.
The viewport and all six panels (Sidebar, Review Panel, Console, Material
Inspector, Properties, Outliner) live as tabs in a single
egui_dock::DockState<SolarxyTab> owned by EguiRenderer in
crates/solarxy-app/src/gui/renderer.rs.
The tab variants are defined in
crates/solarxy-app/src/gui/dock.rs.
Two persisted JSON blobs in Preferences::dock:
| Field | Written by | Read by |
|---|---|---|
last_layout_json |
Auto, on app quit | Startup - restores the window exactly as you left it |
saved_layout_json |
Manual, Layout → Save Layout
|
Layout → Restore Saved Layout |
Layout → Reset Layout to Default rebuilds from default_dock_state in
gui/dock.rs without touching either persisted blob - a safe escape hatch
when a layout gets wedged.
solarxy-validate
is the validation orchestration library. It is consumable as a Rust
library by external vendors who need structured validation results
without a subprocess - DAM systems, training pipelines, asset farms.
Its public wire format is ValidationRunReport. The format is versioned
via a schema_version: u32 field and is intended to remain semver-stable
across patch releases. Vendors should pin to a major version of the
crate, or consume the JSON over the CLI boundary (which is also stable).
The crate ships with two pipeline adapters
(adapters.rs):
-
generic- JSON / Text / TAP / JUnit XML for any CI system. -
github-actions- workflow commands + SARIF for GitHub-native annotation.
Adding a new adapter means a PipelineAdapter impl and a matching
AdapterName variant; see Where to look for X.
A starting-point map. Each row names the directory and one or two key files; line numbers are deliberately omitted to keep this page maintainable across refactors.
| I want to... | Start in |
|---|---|
| Add a sidebar control |
crates/solarxy-app/src/gui/sidebar.rs + gui/snapshot.rs
|
| Add a validation check |
crates/solarxy-core/src/validation/ (one file per check) + validation/mod.rs for dispatch |
| Add an inspection / shading mode |
crates/solarxy-core/src/preferences.rs (the enum) + shader.wgsl (the shader switch) |
| Add a CLI flag | crates/solarxy-cli/src/parser.rs |
| Add a dock tab |
crates/solarxy-app/src/gui/dock.rs - mind the egui_dock serde compatibility for users' persisted last_layout_json
|
| Add a CI pipeline adapter | crates/solarxy-validate/src/adapters.rs |
| Add a file-format loader |
crates/solarxy-formats/src/ (one file per format); integration tests in tests/loaders.rs
|
| Add a menu entry |
crates/solarxy-app/src/gui/menu.rs + gui/actions.rs (the action enum) |
| Change a render pipeline stage |
crates/solarxy-renderer/src/frame.rs (the call sequencing) + the relevant shader in shaders/
|
See also: Contributing · Release Notes · Configuration · Validation Reference
Solarxy - A lightweight, cross-platform 3D model viewer and validator built with Rust and wgpu.
GitHub Repository · Releases & Downloads
© 2026 Marko Koljancic · MIT License
Getting Started
Tutorials
Using Solarxy
Reference
Help
Project