polyscope-render 0.5.10

Rendering backend for polyscope-rs: wgpu engine, shaders, and materials
Documentation
// Curve network edge shader for line rendering
// Renders edges as simple lines with per-edge colors

struct CameraUniforms {
    view: mat4x4<f32>,
    proj: mat4x4<f32>,
    view_proj: mat4x4<f32>,
    inv_proj: mat4x4<f32>,
    camera_pos: vec3<f32>,
    _padding: f32,
}

// Slice plane uniforms for fragment-level slicing
struct SlicePlaneUniforms {
    origin: vec3<f32>,
    enabled: f32,
    normal: vec3<f32>,
    _padding: f32,
}

struct SlicePlanesArray {
    planes: array<SlicePlaneUniforms, 4>,
}

struct CurveNetworkUniforms {
    color: vec4<f32>,         // Base color (RGBA)
    radius: f32,              // Line thickness (for future tube rendering)
    radius_is_relative: u32,  // Whether radius is relative to scene scale
    render_mode: u32,         // 0 = line, 1 = tube
    _padding: f32,
}

@group(0) @binding(0) var<uniform> camera: CameraUniforms;
@group(0) @binding(1) var<uniform> cn_uniforms: CurveNetworkUniforms;
@group(0) @binding(2) var<storage, read> node_positions: array<vec4<f32>>;
@group(0) @binding(3) var<storage, read> node_colors: array<vec4<f32>>;
@group(0) @binding(4) var<storage, read> edge_vertices: array<vec4<f32>>;
@group(0) @binding(5) var<storage, read> edge_colors: array<vec4<f32>>;

@group(1) @binding(0) var<uniform> slice_planes: SlicePlanesArray;

// Matcap textures (Group 2) - declared for pipeline layout compatibility
// Line rendering does not use matcap (no normals available)
@group(2) @binding(0) var matcap_r: texture_2d<f32>;
@group(2) @binding(1) var matcap_g: texture_2d<f32>;
@group(2) @binding(2) var matcap_b: texture_2d<f32>;
@group(2) @binding(3) var matcap_k: texture_2d<f32>;
@group(2) @binding(4) var matcap_sampler: sampler;

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) world_position: vec3<f32>,
    @location(1) edge_color: vec4<f32>,
}

@vertex
fn vs_main(
    @builtin(vertex_index) vertex_index: u32,
) -> VertexOutput {
    var out: VertexOutput;

    // Read edge vertex position
    // Edge vertices are stored as [tail0, tip0, tail1, tip1, ...]
    let position = edge_vertices[vertex_index].xyz;

    // Get edge index (each edge has 2 vertices)
    let edge_index = vertex_index / 2u;

    // Transform position
    out.clip_position = camera.view_proj * vec4<f32>(position, 1.0);
    out.world_position = position;

    // Get color - use edge color if non-zero, otherwise base color
    let ec = edge_colors[edge_index];
    let color_sum = ec.r + ec.g + ec.b;
    if (color_sum > 0.001) {
        out.edge_color = ec;
    } else {
        out.edge_color = cn_uniforms.color;
    }

    return out;
}

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    // Slice plane culling
    for (var i = 0u; i < 4u; i = i + 1u) {
        let plane = slice_planes.planes[i];
        if (plane.enabled > 0.5) {
            let dist = dot(in.world_position - plane.origin, plane.normal);
            if (dist < 0.0) {
                discard;
            }
        }
    }

    // Simple unlit color for lines
    // Lines don't have normals, so we can't do proper lighting
    // Just return the edge color with slight ambient darkening
    let ambient_factor = 0.8;
    let color = in.edge_color.rgb * ambient_factor;

    return vec4<f32>(color, in.edge_color.a);
}