tx2-iff 0.1.0

PPF-IFF (Involuted Fractal Format) - Image codec using Physics-Prime Factorization, 360-prime quantization, and symplectic warping
Documentation
// PPF-based deterministic noise synthesis shader
// Generates texture patterns using 360-prime residue hash

struct Metadata {
    width: u32,
    height: u32,
    levels: u32,
    _padding: u32,
}

struct Region {
    x: u32,
    y: u32,
    w: u32,
    h: u32,
    seed: u32,
    chaos_level: u32,
    scale: u32,
    persistence: u32,
    noise_type: u32,
    base_color_r: u32,
    base_color_g: u32,
    base_color_b: u32,
    amplitude: u32,
}

@group(0) @binding(0) var<storage, read> regions: array<Region>;
@group(0) @binding(1) var<uniform> metadata: Metadata;
@group(0) @binding(2) var<storage, read_write> output: array<u32>;

// 360-prime residue classes for PPF hash
const PRIME_RESIDUES: array<u32, 96> = array<u32, 96>(
    1u, 7u, 11u, 13u, 17u, 19u, 23u, 29u, 31u, 37u, 41u, 43u, 47u, 49u, 53u, 59u,
    61u, 67u, 71u, 73u, 77u, 79u, 83u, 89u, 91u, 97u, 101u, 103u, 107u, 109u, 113u, 119u,
    121u, 127u, 131u, 133u, 137u, 139u, 143u, 149u, 151u, 157u, 161u, 163u, 167u, 169u, 173u, 179u,
    181u, 187u, 191u, 193u, 197u, 199u, 203u, 209u, 211u, 217u, 221u, 223u, 227u, 229u, 233u, 239u,
    241u, 247u, 251u, 253u, 257u, 259u, 263u, 269u, 271u, 277u, 281u, 283u, 287u, 289u, 293u, 299u,
    301u, 307u, 311u, 313u, 317u, 319u, 323u, 329u, 331u, 337u, 341u, 343u, 347u, 349u, 353u, 359u
);

// PPF hash function
fn ppf_hash(x: u32, y: u32, seed: u32) -> f32 {
    let combined = (x ^ (seed * 2654435761u)) + (y ^ (seed * 2246822519u));
    let hash_val = combined * 2654435761u; // Fibonacci hashing
    let residue = hash_val % 360u;

    // Find closest prime residue
    var idx = 0u;
    var min_dist = 360u;
    for (var i = 0u; i < 96u; i++) {
        let dist = abs(i32(residue) - i32(PRIME_RESIDUES[i]));
        if (u32(dist) < min_dist) {
            min_dist = u32(dist);
            idx = i;
        }
    }

    return f32(PRIME_RESIDUES[idx]) / 360.0;
}

// Fixed-point arithmetic (16.16)
fn fixed_from_f32(x: f32) -> i32 {
    return i32(x * 65536.0);
}

fn fixed_mul(a: i32, b: i32) -> i32 {
    let product = i64(a) * i64(b);
    return i32(product >> 16);
}

// Perlin-style gradient noise
fn gradient_noise(x: f32, y: f32, seed: u32) -> f32 {
    let xi = u32(floor(x));
    let yi = u32(floor(y));
    let xf = fract(x);
    let yf = fract(y);

    // Get gradient vectors from hash
    let h00 = ppf_hash(xi, yi, seed);
    let h10 = ppf_hash(xi + 1u, yi, seed);
    let h01 = ppf_hash(xi, yi + 1u, seed);
    let h11 = ppf_hash(xi + 1u, yi + 1u, seed);

    // Convert to gradients
    let g00 = vec2<f32>(cos(h00 * 6.28318), sin(h00 * 6.28318));
    let g10 = vec2<f32>(cos(h10 * 6.28318), sin(h10 * 6.28318));
    let g01 = vec2<f32>(cos(h01 * 6.28318), sin(h01 * 6.28318));
    let g11 = vec2<f32>(cos(h11 * 6.28318), sin(h11 * 6.28318));

    // Dot products
    let d00 = dot(g00, vec2<f32>(xf, yf));
    let d10 = dot(g10, vec2<f32>(xf - 1.0, yf));
    let d01 = dot(g01, vec2<f32>(xf, yf - 1.0));
    let d11 = dot(g11, vec2<f32>(xf - 1.0, yf - 1.0));

    // Smoothstep interpolation
    let u = xf * xf * (3.0 - 2.0 * xf);
    let v = yf * yf * (3.0 - 2.0 * yf);

    // Bilinear interpolation
    let x1 = mix(d00, d10, u);
    let x2 = mix(d01, d11, u);
    return mix(x1, x2, v);
}

// Fractal Brownian Motion
fn fbm(x: f32, y: f32, region: Region) -> f32 {
    var total = 0.0;
    var amplitude = 1.0;
    var frequency = 1.0 / f32(1u << region.scale);
    let octaves = region.chaos_level;
    let persistence_f = f32(region.persistence) / 255.0;

    for (var i = 0u; i < octaves; i++) {
        total += gradient_noise(x * frequency, y * frequency, region.seed + i) * amplitude;
        amplitude *= persistence_f;
        frequency *= 2.0;
    }

    return total;
}

@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let x = global_id.x;
    let y = global_id.y;

    if (x >= metadata.width || y >= metadata.height) {
        return;
    }

    let idx = y * metadata.width + x;

    // Read current pixel
    let current = output[idx];
    var r = current & 0xFFu;
    var g = (current >> 8u) & 0xFFu;
    var b = (current >> 16u) & 0xFFu;

    // Check if pixel is in any texture region
    let region_count = arrayLength(&regions);

    for (var i = 0u; i < region_count; i++) {
        let region = regions[i];

        if (x >= region.x && x < region.x + region.w &&
            y >= region.y && y < region.y + region.h) {

            // Local coordinates
            let local_x = x - region.x;
            let local_y = y - region.y;

            // Generate noise
            let noise = fbm(f32(local_x), f32(local_y), region);

            // Apply to base color
            let amp_f = f32(region.amplitude) / 255.0;
            let noise_scaled = noise * amp_f;

            // Blend with base color
            r = u32(clamp(f32(region.base_color_r) + noise_scaled * 128.0, 0.0, 255.0));
            g = u32(clamp(f32(region.base_color_g) + noise_scaled * 128.0, 0.0, 255.0));
            b = u32(clamp(f32(region.base_color_b) + noise_scaled * 128.0, 0.0, 255.0));

            break; // Only apply first matching region
        }
    }

    // Pack result
    output[idx] = r | (g << 8u) | (b << 16u) | (255u << 24u);
}