Skip to content

scenix v1.6.0 — Shader Nodes And Node Materials

Choose a tag to compare

@github-actions github-actions released this 18 Oct 03:57
· 6 commits to main since this release
943a181

Scenix v1.6.0 — Shader Nodes And Node Materials

Scenix 1.6.0 adds the optional scenix-nodes crate: typed shader graphs,
node materials, and a post-node effect language with WGSL and GLSL ES 3.00
backends. Node materials are a first-class renderer draw path, the post stack
executes generated effects, and the browser preflight compiles graphs to GLSL
before anything is uploaded. Every v1.6 surface is additive and behind the
nodes feature; the default facade build behaves exactly like v1.5.0.

Highlights

  • scenix-nodes is a standalone, no_std-capable CPU crate: build a
    ShaderGraph, validate it, and mutate CPU state with zero GPU involvement.
  • Graphs carry three output ports: fragment_color, fragment_alpha, and an
    optional vertex vertex_offset displacement port. Only the live subgraph is
    validated and lowered; dead nodes are released by construction.
  • A typed ShaderNodeKind vocabulary covers uniforms, vertex attributes,
    world/view fragment sources, texture sampling, splat/component shaping,
    arithmetic, Mix/Clamp/Smoothstep, the five-slot Remap, Fresnel,
    sRGB/linear conversion, four lighting styles, tone mappers, and fog. Nodes
    carry stage metadata, so fragment-only or post-only nodes in another stage
    produce specific NodeDiagnostics instead of broken shaders.
  • The WGSL backend emits modules that match the renderer bind contract exactly:
    group 0 frame, group 1 object, group 2 material (uniform + sampler +
    texture_2d), group 3 set up for fragment-stage lights, and six varyings that
    mirror the built-in vertex layout. Time compiles to the frame elapsed slot.
  • Codegen deduplicates common subexpressions, prunes dead nodes, and treats
    vec3 lighting/fog results correctly (alpha rides the vec4 constructor
    because WGSL forbids implicit vec3 → vec4 casts).
  • NodeMaterial pairs a graph with CPU state (base color, emissive, metallic,
    roughness, alpha mode/cutoff, double-sided, texture id). It reports the
    FEATURE_NODE_GRAPH bit, a Custom shader-kind pipeline key, a stable graph
    hash that ignores live CPU state, and optional serde support.
  • Renderer::register_node_material (behind the renderer's nodes feature)
    registers slots, packs node uniforms in the standard material block, builds
    node pipelines lazily per NodeMaterialSlot, switches pipelines per draw,
    buckets transparency from the slot's alpha mode, and rejects unregistered
    node materials during culling with the same error pipeline as built-ins.
  • PostNodeEffect post graphs ship atomic presets (passthrough, vignette,
    desaturate, posterize, pixelate, color grade, exposure) plus
    scenix-post::NodeEffectProgram, which owns one generated module, builds
    per-format pipelines lazily, and drives the [f32; 8] parameter contract
    through the standard post pass.
  • The scenix-wasm browser preflight compiles a serialized NodeMaterial
    into GLSL with a diagnostic payload (compile_node_material_glsl) or
    validates it without codegen (validate_node_material_json) — no GPU, no
    renderer state, panic-free JsValue surfaces.
  • Color-like nodes (lighting, tone mapping, fog, conversions) accept rgba base
    colors directly and drop alpha in codegen, so scripts authored against vec4
    colors flow through unchanged.

Small Example

use scenix::{
    generate_material_wgsl, LightingStyle, Material, NodeInput, NodeMaterial, ShaderGraph,
    ShaderNodeKind, UniformInput, WgslOptions,
};

// Base color pulses over time, then feeds a Lambert lighting term.
let mut graph = ShaderGraph::new();
let base = graph.push(ShaderNodeKind::Uniform(UniformInput::BaseColor));
let time = graph.push(ShaderNodeKind::Uniform(UniformInput::Time));
let pulse = graph.add(
    ShaderNodeKind::Multiply,
    vec![NodeInput::Node(base), NodeInput::Node(time)],
);
let lit = graph.chain(ShaderNodeKind::Lighting(LightingStyle::Lambert), pulse);
graph.add_fragment_output(lit, None);

let material = NodeMaterial::new("pulse", graph);
assert!(material.validate().is_empty());
assert!(material.feature_bits() & scenix::FEATURE_NODE_GRAPH != 0);

let wgsl = generate_material_wgsl(&material, &WgslOptions::default()).unwrap();
// wgsl.source() is renderer-ready: bind groups 0..=3 follow the scenix
// contract, and Time resolved to frame.resolution.z.

Feature Flags

  • nodes: enables scenix-nodes through the facade with curated re-exports
    (node vocabulary, materials, generators, diagnostics, parameter slots).
  • nodes + renderer: node-material slots enter the draw path with lazy
    pipelines and per-draw set_pipeline switching.
  • nodes + post: NodeEffectProgram executes generated post graphs.
  • nodes + wasm: browser-side GLSL preflight for node editors.
  • scenix-nodes standalone: no_std-capable CPU crate (std/serde features).

Examples

cargo run -p scenix --example nodes_material --features nodes
cargo run -p scenix --example nodes_wgsl --features nodes
cargo run -p scenix --example node_post_effect --features nodes

Compatibility

  • All 18 workspace crates are version 1.6.0 and require Rust 1.98.
  • No existing enum gained variants; default features are unchanged.
  • The renderer frame uniform now packs [width, height, elapsed, 1 / height];
    built-in shaders are unaffected, and direct FrameUniform consumers outside
    scenix should account for the elapsed slot.
  • Node graphs that cannot resolve produce a typed NodeDiagnostic
    (StageUnsupported, port mismatches, cycles, UnknownNode) rather than a
    panicking pipeline; NodeMaterial::validate covers the fragment stage and
    ShaderGraph::validate(Stage::Vertex) covers displacement ports explicitly.
  • GPU-gated tests (SCENIX_RUN_GPU_TESTS=1) cover headless node rendering,
    mixed node/builtin draws, culling rejection, and registration validation;
    dedicated benchmarks cover graph build/lower hot paths.

See the full changelog and the
node API guide for API and verification
details.