arcane-core 0.26.1

Core library for Arcane - agent-native 2D game engine (TypeScript runtime, renderer, platform layer)
Documentation
// 2D SDF composition operations and domain transforms for the Arcane game engine.
//
// These operations combine and transform signed distance fields produced by
// the primitives in sdf_primitives.wgsl.
//
// Ported from Inigo Quilez's reference:
//   https://iquilezles.org/articles/distfunctions2d/
//
// Usage: Import alongside sdf_primitives.wgsl into fragment shaders that
// build complex procedural shapes from SDF primitives.

// ============================================================================
// Boolean operations
// ============================================================================

/// Union: the exterior of both shapes becomes the exterior of the result.
/// Returns the minimum distance (closest surface).
fn op_union(d1: f32, d2: f32) -> f32 {
    return min(d1, d2);
}

/// Subtraction: carves d2 out of d1. The interior of d2 becomes exterior.
fn op_subtract(d1: f32, d2: f32) -> f32 {
    return max(d1, -d2);
}

/// Intersection: only the region inside both shapes remains interior.
fn op_intersect(d1: f32, d2: f32) -> f32 {
    return max(d1, d2);
}

/// Smooth union with blending factor k. Larger k = smoother blend.
/// k = 0 degenerates to hard union. Typical values: 0.1 to 1.0.
fn op_smooth_union(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0.0, 1.0);
    return mix(d2, d1, h) - k * h * (1.0 - h);
}

/// Smooth subtraction with blending factor k. Carves d2 from d1 with
/// a smooth fillet at the intersection.
fn op_smooth_subtract(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 - 0.5 * (d1 + d2) / k, 0.0, 1.0);
    return mix(d1, -d2, h) + k * h * (1.0 - h);
}

// ============================================================================
// Modifiers
// ============================================================================

/// Round: expand the shape outward by radius r, rounding all corners.
/// Equivalent to a Minkowski sum with a circle of radius r.
fn op_round(d: f32, r: f32) -> f32 {
    return d - r;
}

/// Onion: hollow out a shape, creating a shell of thickness r.
/// Converts a filled shape into a ring/outline.
fn op_onion(d: f32, r: f32) -> f32 {
    return abs(d) - r;
}

// ============================================================================
// Domain transforms
//
// These modify the input point p before passing it to an SDF primitive,
// effectively transforming the shape in space.
// ============================================================================

/// Rotate a point by angle (in radians) around the origin.
/// Apply before evaluating an SDF to rotate the shape.
fn rotate_rad(p: vec2<f32>, angle: f32) -> vec2<f32> {
    let c = cos(angle);
    let s = sin(angle);
    return vec2<f32>(
        c * p.x + s * p.y,
        -s * p.x + c * p.y
    );
}

/// Infinite repetition: tiles space with the given spacing.
/// Returns a point in the range [-spacing/2, spacing/2] per axis.
///
/// Note: This creates infinite copies. For finite repetition, use
/// clamp on the cell index instead.
fn op_repeat(p: vec2<f32>, spacing: vec2<f32>) -> vec2<f32> {
    return p - spacing * round(p / spacing);
}

/// Mirror across the x-axis (left-right symmetry).
/// Folds the point into the positive-x half-plane, so you only
/// need to define the shape for x >= 0.
fn op_symmetry_x(p: vec2<f32>) -> vec2<f32> {
    return vec2<f32>(abs(p.x), p.y);
}