radiance 0.7.1

Video art software designed for live performance
Documentation
struct Uniforms {
    // Audio levels, high/mid/low/level, [0.0, 1.0]
    iAudio: vec4<f32>,

    // Time, measured in beats. Wraps around to 0 every 16 beats, [0.0, 16.0)
    iTime: f32,

    iFrequency: f32,

    // Intensity slider, [0.0, 1.0]
    iIntensity: f32,

    // Intensity slider integrated with respect to wall time mod 1024, [0.0, 1024.0)
    iIntensityIntegral: f32,

    // Resolution of the output pattern
    iResolution: vec2<f32>,

    // (Ideal) output rate in frames per second
    iStep: f32,
}

@group(0) @binding(0)
var<uniform> global: Uniforms;

@group(1) @binding(0)
var iSampler: sampler;

@group(1) @binding(1)
var iInputsTex: binding_array<texture_2d<f32>>;

@group(1) @binding(2)
var iNoiseTex: texture_2d<f32>;

@group(1) @binding(3)
var iChannelsTex: binding_array<texture_2d<f32>>;

var<private> iAudio: vec4<f32>;
var<private> iTime: f32;
var<private> iFrequency: f32;
var<private> iIntensity: f32;
var<private> iIntensityIntegral: f32;
var<private> iResolution: vec2<f32>;
var<private> iStep: f32;

var<private> aspectCorrection: vec2<f32>;
var<private> defaultPulse: f32;
var<private> onePixel: vec2<f32>;

// Aliases to audio levels
var<private> iAudioLow: f32;
var<private> iAudioMid: f32;
var<private> iAudioHi: f32;
var<private> iAudioLevel: f32;

const pi: f32 = 3.1415926535897932384626433832795;

fn modulo(x: f32, y: f32) -> f32 {
    return x - y * floor(x / y);
}

//float lin_step(float v) {
//    return v * iStep * iFPS;
//}
//float exp_step(float v) {
//    return pow(v, iStep * iFPS);
//}
//

// Utilities to convert from an RGB vec3 to an HSV vec3
// 0 <= H, S, V <= 1
fn rgb2hsv(c: vec3<f32>) -> vec3<f32> {
    let K = vec4<f32>(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    let p = mix(vec4<f32>(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
    let q = mix(vec4<f32>(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

    let d = q.x - min(q.w, q.y);
    let e = 1.0e-10;
    return vec3<f32>(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

fn hsv2rgb(c: vec3<f32>) -> vec3<f32> {
    let K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    let p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, vec3<f32>(0.0), vec3<f32>(1.0)), c.y);
}

// Utilities to convert from an RGB vec3 to a YUV vec3
// 0 <= Y, U, V <= 1 (*not* -1 <= U, V <= 1)
// U is greenish<->bluish; V is bluish<->redish
// https://en.wikipedia.org/wiki/YUV#Full_swing_for_BT.601
fn rgb2yuv(rgb: vec3<f32>) -> vec3<f32> {
    let y = rgb.r *  0.2126  + rgb.g *  0.7152  + rgb.b *  0.0722;
    let u = rgb.r * -0.09991 + rgb.g * -0.33609 + rgb.b *  0.436;
    let v = rgb.r *  0.615   + rgb.g * -0.55861 + rgb.b * -0.05639;
    return vec3(y, (u + 1.) * 0.5, (v + 1.) * 0.5);
}
fn yuv2rgb(yuv: vec3<f32>) -> vec3<f32> {
    let y = yuv.x;
    let u = yuv.y * 2. - 1.;
    let v = yuv.z * 2. - 1.;

    let r = y                + v *  1.28033;
    let g = y + u * -0.21482 + v * -0.38059;
    let b = y + u *  2.12798;
    let rgb = vec3<f32>(r, g, b);
    return clamp(rgb, vec3<f32>(0.0), vec3<f32>(1.0));
}


// Turn non-premultipled alpha RGBA into premultipled alpha RGBA
fn premultiply(c: vec4<f32>) -> vec4<f32> {
    return vec4<f32>(c.rgb * c.a, c.a);
}

// Turn premultipled alpha RGBA into non-premultipled alpha RGBA
fn demultiply(c: vec4<f32>) -> vec4<f32> {
    return clamp(vec4<f32>(c.rgb / c.a, c.a), vec4<f32>(0.), vec4<f32>(1.));
}

// Alpha-compsite two colors, putting one on top of the other. Everything is premultipled
fn composite(under: vec4<f32>, over: vec4<f32>) -> vec4<f32> {
    let a_out: f32 = 1. - (1. - over.a) * (1. - under.a);
    return clamp(vec4<f32>((over.rgb + under.rgb * (1. - over.a)), a_out), vec4<f32>(0.), vec4<f32>(1.));
}

// Sawtooth wave
fn sawtooth(x: f32, t_up: f32) -> f32 {
    let x2 = modulo(x + t_up, 1.);
    return x2 / t_up * step(x2, t_up) +
           (1. - x2) / (1. - t_up) * (1. - step(x2, t_up));
}

// Box from [0, 0] to (1, 1)
fn box(p: vec2<f32>) -> f32 {
    let b = step(vec2<f32>(0.), p) - step(vec2<f32>(1.), p);
    return b.x * b.y;
}


// Predictable randomness
fn rand(c: f32) -> f32 {
    return fract(sin(c * 12.9898) * 43758.5453);
}

fn rand2(c: vec2<f32>) -> f32 {
    return fract(sin(dot(c, vec2(12.9898,78.233))) * 43758.5453);
}

fn rand3(c: vec3<f32>) -> f32 {
    return fract(sin(dot(c, vec3(12.9898,78.233, 52.942))) * 43758.5453);
}

fn rand4(c: vec4<f32>) -> f32 {
    return fract(sin(dot(c, vec4(12.9898, 78.233, 52.942, 35.291))) * 43758.5453);
}

fn noise(p: f32) -> f32 {
    let i = i32(floor(p));
    let x1 = fract(p);
    // x = .5*(1.-cos(M_PI*x));
    let x2 = 3. * x1 * x1 - 2. * x1 * x1 * x1;
    let a = rand(f32(i + 0));
    let b = rand(f32(i + 1));
    return mix(a, b, x2);
}

fn noise2(p: vec2<f32>) -> f32 {
    let ij = vec2<i32>(floor(p));
    let xy1 = fract(p);
    // xy = .5*(1.-cos(M_PI*xy));
    let xy2 = 3. * xy1 * xy1 - 2. * xy1 * xy1 * xy1;
    let a = rand2(vec2<f32>(ij+vec2<i32>(0, 0)));
    let b = rand2(vec2<f32>(ij+vec2<i32>(1, 0)));
    let c = rand2(vec2<f32>(ij+vec2<i32>(0, 1)));
    let d = rand2(vec2<f32>(ij+vec2<i32>(1, 1)));
    let x1 = mix(a, b, xy2.x);
    let x2 = mix(c, d, xy2.x);
    return mix(x1, x2, xy2.y);
}

fn noise3(p: vec3<f32>) -> f32 {
    let ijk = vec3<i32>(floor(p));
    let xyz1 = fract(p);
    // xyz = .5*(1.-cos(M_PI*xyz));
    let xyz2 = 3. * xyz1 * xyz1 - 2. * xyz1 * xyz1 * xyz1;
    let a = rand3(vec3<f32>(ijk+vec3<i32>(0, 0, 0)));
    let b = rand3(vec3<f32>(ijk+vec3<i32>(1, 0, 0)));
    let c = rand3(vec3<f32>(ijk+vec3<i32>(0, 1, 0)));
    let d = rand3(vec3<f32>(ijk+vec3<i32>(1, 1, 0)));
    let e = rand3(vec3<f32>(ijk+vec3<i32>(0, 0, 1)));
    let f = rand3(vec3<f32>(ijk+vec3<i32>(1, 0, 1)));
    let g = rand3(vec3<f32>(ijk+vec3<i32>(0, 1, 1)));
    let h = rand3(vec3<f32>(ijk+vec3<i32>(1, 1, 1)));
    let x1 = mix(a, b, xyz2.x);
    let x2 = mix(c, d, xyz2.x);
    let y1 = mix(x1, x2, xyz2.y);
    let x3 = mix(e, f, xyz2.x);
    let x4 = mix(g, h, xyz2.x);
    let y2 = mix(x3, x4, xyz2.y);
    return mix(y1, y2, xyz2.z);
}

fn noise4(p: vec4<f32>) -> f32 {
    let ijkl = vec4<i32>(floor(p));
    let xyzw1 = fract(p);
    // xyz = .5*(1.-cos(M_PI*xyz));
    let xyzw2 = 3. * xyzw1 * xyzw1 - 1. * xyzw1 * xyzw1 * xyzw1;
    let a = rand4(vec4<f32>(ijkl+vec4<i32>(0, 0, 0, 0)));
    let b = rand4(vec4<f32>(ijkl+vec4<i32>(1, 0, 0, 0)));
    let c = rand4(vec4<f32>(ijkl+vec4<i32>(0, 1, 0, 0)));
    let d = rand4(vec4<f32>(ijkl+vec4<i32>(1, 1, 0, 0)));
    let e = rand4(vec4<f32>(ijkl+vec4<i32>(0, 0, 1, 0)));
    let f = rand4(vec4<f32>(ijkl+vec4<i32>(1, 0, 1, 0)));
    let g = rand4(vec4<f32>(ijkl+vec4<i32>(0, 1, 1, 0)));
    let h = rand4(vec4<f32>(ijkl+vec4<i32>(1, 1, 1, 0)));
    let i = rand4(vec4<f32>(ijkl+vec4<i32>(0, 0, 0, 1)));
    let j = rand4(vec4<f32>(ijkl+vec4<i32>(1, 0, 0, 1)));
    let k = rand4(vec4<f32>(ijkl+vec4<i32>(0, 1, 0, 1)));
    let l = rand4(vec4<f32>(ijkl+vec4<i32>(1, 1, 0, 1)));
    let m = rand4(vec4<f32>(ijkl+vec4<i32>(0, 0, 1, 1)));
    let n = rand4(vec4<f32>(ijkl+vec4<i32>(1, 0, 1, 1)));
    let o = rand4(vec4<f32>(ijkl+vec4<i32>(0, 1, 1, 1)));
    let q = rand4(vec4<f32>(ijkl+vec4<i32>(1, 1, 1, 1)));
    let x1 = mix(a, b, xyzw2.x);
    let x2 = mix(c, d, xyzw2.x);
    let y1 = mix(x1, x2, xyzw2.y);
    let x3 = mix(e, f, xyzw2.x);
    let x4 = mix(g, h, xyzw2.x);
    let y2 = mix(x3, x4, xyzw2.y);
    let z1 = mix(y1, y2, xyzw2.z);

    let x5 = mix(i, j, xyzw2.x);
    let x6 = mix(k, l, xyzw2.x);
    let y3 = mix(x5, x6, xyzw2.y);
    let x7 = mix(m, n, xyzw2.x);
    let x8 = mix(o, q, xyzw2.x);
    let y4 = mix(x7, x8, xyzw2.y);
    let z2 = mix(y3, y4, xyzw2.z);
    return mix(z1, z2, xyzw2.w);
}

//float hmax(vec2 v) {
//    return max(v.r,v.g);
//}
//float hmax(vec3 v) {
//    return max(hmax(v.rg),v.b);
//}
//float hmax(vec4 v) {
//    return hmax(max(v.rg,v.ba));
//}

fn inverse2(m: mat2x2<f32>) -> mat2x2<f32> {
    let a = m[0][0];
    let b = m[1][0];
    let c = m[0][1];
    let d = m[1][1];

    let det = a * d - b * c;

    return mat2x2<f32>(d, -c, -b, a) * (1. / det);
}

// Source adapted from https://github.com/glslify/glsl-inverse/blob/master/index.glsl
fn inverse3(m: mat3x3<f32>) -> mat3x3<f32> {
    let a00 = m[0][0];
    let a01 = m[0][1];
    let a02 = m[0][2];
    let a10 = m[1][0];
    let a11 = m[1][1];
    let a12 = m[1][2];
    let a20 = m[2][0];
    let a21 = m[2][1];
    let a22 = m[2][2];

    let b01 = a22 * a11 - a12 * a21;
    let b11 = -a22 * a10 + a12 * a20;
    let b21 = a21 * a10 - a11 * a20;

    let det = a00 * b01 + a01 * b11 + a02 * b21;

    return mat3x3<f32>(
        b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),
        b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),
        b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10),
    ) * (1. / det);
}

// From https://gist.github.com/rsms/9d9e7c4eadf9fe23da0bf0bfb96bc2e6#file-webgpu-infinite-world-grid-cc-L26
fn inverse4(m: mat4x4<f32>) -> mat4x4<f32> {
    // Note: wgsl does not have an inverse() (matrix inverse) function built in.
    // Source adapted from https://github.com/glslify/glsl-inverse/blob/master/index.glsl
    let a00 = m[0][0];
    let a01 = m[0][1];
    let a02 = m[0][2];
    let a03 = m[0][3];
    let a10 = m[1][0];
    let a11 = m[1][1];
    let a12 = m[1][2];
    let a13 = m[1][3];
    let a20 = m[2][0];
    let a21 = m[2][1];
    let a22 = m[2][2];
    let a23 = m[2][3];
    let a30 = m[3][0];
    let a31 = m[3][1];
    let a32 = m[3][2];
    let a33 = m[3][3];
    let b00 = a00 * a11 - a01 * a10;
    let b01 = a00 * a12 - a02 * a10;
    let b02 = a00 * a13 - a03 * a10;
    let b03 = a01 * a12 - a02 * a11;
    let b04 = a01 * a13 - a03 * a11;
    let b05 = a02 * a13 - a03 * a12;
    let b06 = a20 * a31 - a21 * a30;
    let b07 = a20 * a32 - a22 * a30;
    let b08 = a20 * a33 - a23 * a30;
    let b09 = a21 * a32 - a22 * a31;
    let b10 = a21 * a33 - a23 * a31;
    let b11 = a22 * a33 - a23 * a32;
    let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
    return mat4x4<f32>(
      vec4<f32>(
        a11 * b11 - a12 * b10 + a13 * b09,
        a02 * b10 - a01 * b11 - a03 * b09,
        a31 * b05 - a32 * b04 + a33 * b03,
        a22 * b04 - a21 * b05 - a23 * b03),
      vec4<f32>(
        a12 * b08 - a10 * b11 - a13 * b07,
        a00 * b11 - a02 * b08 + a03 * b07,
        a32 * b02 - a30 * b05 - a33 * b01,
        a20 * b05 - a22 * b02 + a23 * b01),
      vec4<f32>(
        a10 * b10 - a11 * b08 + a13 * b06,
        a01 * b08 - a00 * b10 - a03 * b06,
        a30 * b04 - a31 * b02 + a33 * b00,
        a21 * b02 - a20 * b04 - a23 * b00),
      vec4<f32>(
        a11 * b07 - a10 * b09 - a12 * b06,
        a00 * b09 - a01 * b07 + a02 * b06,
        a31 * b01 - a30 * b03 - a32 * b00,
        a20 * b03 - a21 * b01 + a22 * b00)
    ) * (1.0 / det);
}

// Adds back in the alpha channel for a modified RGB color
// dimming the color as necessary
fn add_alpha_dimming(rgb: vec3<f32>, a: f32) -> vec4<f32> {
    let min_new_alpha = max(max(rgb.r, rgb.g), rgb.b);
    let scale = min(1., a / min_new_alpha);
    return vec4<f32>(rgb * scale, a);
}

// Adds back in the alpha channel for a modified RGB color
// increasing opacity as necessary
fn add_alpha(rgb: vec3<f32>, a: f32) -> vec4<f32> {
    return vec4<f32>(rgb, max(max(max(rgb.r, rgb.g), rgb.b), a));
}

//#line 1