Skip to content

Instantly share code, notes, and snippets.

@ricardomatias
Forked from munrocket/wgsl_3d_sdf.md
Created August 4, 2021 15:28
Show Gist options
  • Save ricardomatias/d90fad34fc3e6a8e5a133c4ce6b6378e to your computer and use it in GitHub Desktop.
Save ricardomatias/d90fad34fc3e6a8e5a133c4ce6b6378e to your computer and use it in GitHub Desktop.

Revisions

  1. @munrocket munrocket revised this gist Aug 2, 2021. 1 changed file with 40 additions and 0 deletions.
    40 changes: 40 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -400,6 +400,46 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>
    ```
    <img src="https://habrastorage.org/webt/ad/9t/cu/ad9tcutikuqz9yxdrpdquugqkrs.jpeg" width="150px">

    #### Triangle - exact
    ```rs
    fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    let cb = c - b; let pb = p - b;
    let ac = a - c; let pc = p - c;
    let nor = cross(ba, ac);
    let d1 = ba * clamp(dot(ba, pa) / dot(ba, ba), 0., 1.) - pa;
    let d2 = cb * clamp(dot(cb, pb) / dot(cb, cb), 0., 1.) - pb;
    let d3 = ac * clamp(dot(ac, pc) / dot(ac, ac), 0., 1.) - pc;
    let k0 = min(min(dot(d1, d1), dot(d2, d2)), dot(d3, d3));
    let k1 = dot(nor, pa) * dot(nor, pa) / dot(nor, nor);
    let t = sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) +
    sign(dot(cross(ac, nor), pc));
    return sqrt(select(k0, k1, t < 2.));
    }
    ```
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px">

    #### Quad - exact
    ```rs
    fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    let cb = c - b; let pb = p - b;
    let dc = d - c; let pc = p - c;
    let ad = a - d; let pd = p - d;
    let nor = cross(ba, ad);
    let d1 = ba * clamp(dot(ba, pa) / dot(ba, ba), 0., 1.) - pa;
    let d2 = cb * clamp(dot(cb, pb) / dot(cb, cb), 0., 1.) - pb;
    let d3 = dc * clamp(dot(dc, pc) / dot(dc, dc), 0., 1.) - pc;
    let d4 = ad * clamp(dot(ad, pd) / dot(ad, ad), 0., 1.) - pd;
    let k0 = min(min(dot(d1, d1), dot(d2, d2)), min(dot(d3, d3), dot(d4, d4)));
    let k1 = dot(nor, pa) * dot(nor, pa) / dot(nor, nor);
    let t = sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) +
    sign(dot(cross(dc, nor), pc)) + sign(dot(cross(ad, nor), pd));
    return sqrt(select(k0, k1, t < 3.));
    }
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
  2. @munrocket munrocket revised this gist Jul 28, 2021. 1 changed file with 2 additions and 6 deletions.
    8 changes: 2 additions & 6 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -566,13 +566,9 @@ fn opTransform(p: vec3<f32>, transform: mat4x4<f32>) -> vec3<f32> {
    ```rs
    fn opSymmetryX(p: vec3<f32>) -> vec3<f32> { return vec3<f32>(abs(p.x), p.y, p.z); }

    fn opSymmetryY(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.x, abs(p.y), p.z);
    }
    fn opSymmetryY(p: vec3<f32>) -> vec3<f32> { return vec3<f32>(p.x, abs(p.y), p.z); }

    fn opSymmetryZ(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.x, p.y, abs(p.z));
    }
    fn opSymmetryZ(p: vec3<f32>) -> vec3<f32> { return vec3<f32>(p.x, p.y, abs(p.z)); }
    //let d = sdfPrimitive3d(opSymmetryX(p));
    ```
    <img src="https://habrastorage.org/webt/fp/13/-t/fp13-tocnb3scya_3g_jx7h1s5w.jpeg" width="150px"/>
  3. @munrocket munrocket revised this gist Jul 22, 2021. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -217,7 +217,7 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f
    let papa = dot(p - a, p - a);
    let paba = dot(p - a, b - a) / baba;
    let x = sqrt(papa - paba * paba * baba);
    let cax = max(0.0, x - select(ra, rb, paba < 0.5));
    let cax = max(0.0, x - select(rb, ra, paba < 0.5));
    let cay = abs(paba - 0.5) - 0.5;
    let k = rba * rba + baba;
    let f = clamp((rba * (x - ra) + paba * baba) / k, 0.0, 1.0);
    @@ -378,20 +378,20 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>
    let x = (vec2<f32>(h, -h) - q) / 2.;
    let uv = sign(x) * pow(abs(x), vec2<f32>(1. / 3.));
    let t = clamp(uv.x + uv.y - kx, 0., 1.);
    let w = d + (c + b * t) * t;
    res = vec2<f32>(dot(w, w), t);
    let f = d + (c + b * t) * t;
    res = vec2<f32>(dot(f, f), t);
    } else {
    let z = sqrt(-p1);
    let v = acos(q / (p1 * z * 2.)) / 3.;
    let m = cos(v);
    let n = sin(v) * 1.732050808;
    let t = clamp(vec2<f32>(m + m, -n - m) * z - kx, vec2<f32>(0.0), vec2<f32>(1.0));
    let v = d + (c + b * t.x) * t.x;
    var dis: f32 = dot(v, v);
    let f = d + (c + b * t.x) * t.x;
    var dis: f32 = dot(f, f);
    res = vec2<f32>(dis, t.x);

    let w = d + (c + b * t.y) * t.y;
    dis = dot(w, w);
    let g = d + (c + b * t.y) * t.y;
    dis = dot(g, g);
    res = select(res, vec2<f32>(dis, t.y), dis < res.x);
    }
    res.x = sqrt(res.x);
  4. @munrocket munrocket revised this gist Jul 22, 2021. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -81,7 +81,7 @@ fn sdTorus(p: vec3<f32>, R: f32, r: f32) -> f32 {
    ```rs
    fn sdCappedTorus(p: vec3<f32>, R: f32, r: f32, sincos: vec2<f32>) -> f32 {
    let q = vec3<f32>(abs(p.x), p.y, p.z);
    let k = select(dot(q.xy, sincos), length(q.xy), sincos.y * q.x > sincos.x * q.y);
    let k = select(length(q.xy), dot(q.xy, sincos), sincos.y * q.x > sincos.x * q.y);
    return sqrt(dot(q, q) + R * R - 2. * R * k) - r;
    }
    ```
    @@ -128,7 +128,7 @@ fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let x2 = x * x;
    let y2 = y * y * baba;
    let d = x2 * step(0., x) + y2 * step(0., y);
    let d2 = select(-min(x2, y2), d, max(x, y) < 0.);
    let d2 = select(d, -min(x2, y2), max(x, y) < 0.);
    return sign(d2) * sqrt(abs(d2)) / baba;
    }
    ```
    @@ -190,7 +190,7 @@ fn sdConeBound(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    let q = vec2<f32>(length(p.xz), -p.y);
    let d = length(q - sincos * max(dot(q, sincos), 0.));
    return d * select(1., -1., q.x * sincos.y - q.y * sincos.x > 0.0);
    return d * select(-1., 1., q.x * sincos.y - q.y * sincos.x > 0.0);
    }
    ```
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px">
    @@ -201,9 +201,9 @@ fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    let k1 = vec2<f32>(r2, h);
    let k2 = vec2<f32>(r2 - r1, 2. * h);
    let ca = vec2<f32>(q.x - min(q.x, select(r1, r2, q.y < 0.)), abs(q.y) - h);
    let ca = vec2<f32>(q.x - min(q.x, select(r2, r1, q.y < 0.)), abs(q.y) - h);
    let cb = q - k1 + k2 * clamp(dot(k1 - q, k2) / dot(k2, k2), 0., 1.);
    let s = select(-1., 1., cb.x < 0. && ca.y < 0.);
    let s = select(1., -1., cb.x < 0. && ca.y < 0.);
    return s * sqrt(min(dot(ca, ca), dot(cb, cb)));
    }
    ```
    @@ -223,7 +223,7 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f
    let f = clamp((rba * (x - ra) + paba * baba) / k, 0.0, 1.0);
    let cbx = x - ra - f * rba;
    let cby = paba - f;
    let s = select(-1., 1., cbx < 0.0 && cay < 0.0);
    let s = select(1., -1., cbx < 0.0 && cay < 0.0);
    return s * sqrt(min(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba));
    }
    ```
    @@ -317,7 +317,7 @@ fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {
    fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    let m2 = h * h + 0.25;
    var xz: vec2<f32> = abs(p.xz);
    xz = select(xz.yx, xz, xz[1] > xz[0]);
    xz = select(xz, xz.yx, xz[1] > xz[0]);
    xz = xz - vec2<f32>(0.5);

    let q = vec3<f32>(xz[1], h * p.y - 0.5 * xz[0], h * xz[0] + 0.5 * p.y);
    @@ -392,7 +392,7 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>

    let w = d + (c + b * t.y) * t.y;
    dis = dot(w, w);
    res = select(vec2<f32>(dis, t.y), res, dis < res.x);
    res = select(res, vec2<f32>(dis, t.y), dis < res.x);
    }
    res.x = sqrt(res.x);
    return res;
  5. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -380,7 +380,7 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>
    let t = clamp(uv.x + uv.y - kx, 0., 1.);
    let w = d + (c + b * t) * t;
    res = vec2<f32>(dot(w, w), t);
    } else{
    } else {
    let z = sqrt(-p1);
    let v = acos(q / (p1 * z * 2.)) / 3.;
    let m = cos(v);
    @@ -392,7 +392,7 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>

    let w = d + (c + b * t.y) * t.y;
    dis = dot(w, w);
    if (dis < res.x) { res = vec2<f32>(dis, t.y); }
    res = select(vec2<f32>(dis, t.y), res, dis < res.x);
    }
    res.x = sqrt(res.x);
    return res;
  6. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 45 additions and 0 deletions.
    45 changes: 45 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -355,6 +355,51 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px">

    #### Quadratic Bezier - exact
    ```rs
    fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32> {
    let a = B - A;
    let b = A - 2. * B + C;
    let c = a * 2.;
    let d = A - p;
    let kk = 1. / dot(b, b);
    let kx = kk * dot(a, b);
    let ky = kk * (2. * dot(a, a) + dot(d, b)) / 3.;
    let kz = kk * dot(d, a);

    let p1 = ky - kx * kx;
    let p3 = p1 * p1 * p1;
    let q = kx * (2.0 * kx * kx - 3.0 * ky) + kz;
    var h: f32 = q * q + 4. * p3;

    var res: vec2<f32>;
    if (h >= 0.) {
    h = sqrt(h);
    let x = (vec2<f32>(h, -h) - q) / 2.;
    let uv = sign(x) * pow(abs(x), vec2<f32>(1. / 3.));
    let t = clamp(uv.x + uv.y - kx, 0., 1.);
    let w = d + (c + b * t) * t;
    res = vec2<f32>(dot(w, w), t);
    } else{
    let z = sqrt(-p1);
    let v = acos(q / (p1 * z * 2.)) / 3.;
    let m = cos(v);
    let n = sin(v) * 1.732050808;
    let t = clamp(vec2<f32>(m + m, -n - m) * z - kx, vec2<f32>(0.0), vec2<f32>(1.0));
    let v = d + (c + b * t.x) * t.x;
    var dis: f32 = dot(v, v);
    res = vec2<f32>(dis, t.x);

    let w = d + (c + b * t.y) * t.y;
    dis = dot(w, w);
    if (dis < res.x) { res = vec2<f32>(dis, t.y); }
    }
    res.x = sqrt(res.x);
    return res;
    }
    ```
    <img src="https://habrastorage.org/webt/ad/9t/cu/ad9tcutikuqz9yxdrpdquugqkrs.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
  7. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 0 additions and 60 deletions.
    60 changes: 0 additions & 60 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -355,66 +355,6 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px">

    #### Bunny - bound
    ```rs
    fn m4(a1: f32, a2: f32, a3: f32, a4: f32, b1: f32, b2: f32, b3: f32, b4: f32,
    c1: f32, c2: f32, c3: f32, c4: f32, d1: f32, d2: f32, d3: f32, d4: f32) -> mat4x4<f32> {
    return mat4x4<f32>(vec4<f32>(a1, a2, a3, a4), vec4<f32>(b1, b2, b3, b4),
    vec4<f32>(c1, c2, c3, c4), vec4<f32>(d1, d2, d3, d4));
    }
    fn bunny(p: vec3<f32>) -> f32 {
    if (dot(p, p) > 1.) { return length(p) - .8; }
    let q = vec4<f32>(p, 1.);
    let f00=sin(m4(-3.02,1.95,-3.42,-.6,3.08,.85,-2.25,-.24,-.29,1.16,-3.74,2.89,-.71,4.5,-3.24,-3.5)*q);
    let f01=sin(m4(-.4,-3.61,3.23,-.14,-.36,3.64,-3.91,2.66,2.9,-.54,-2.75,2.71,7.02,-5.41,-1.12,-7.41)*q);
    let f02=sin(m4(1.77,1.28,4.29,3.2,3.49,2.81,.64,-2.79,-3.15,-2.14,3.85,-1.83,2.07,-4.49,-5.33,2.17)*-q);
    let f03=sin(m4(-.49,.68,3.05,.42,-2.87,.78,3.78,-3.41,-2.65,.33,.07,-.64,-3.24,-5.9,1.14,-4.71)*q);
    let f10=sin(m4(-.34,.06,-.59,-.76,.1,-.19,-.12,.44,.64,-.02,-.26,.15,-.16,.21,.91,.15)*f00+
    m4(.01,.54,-.77,.11,.06,-.14,.43,.51,-.18,.08,.39,.2,.33,-.49,-.1,.19)*f01+
    m4(.27,.22,.43,.53,.18,-.17,.23,-.64,-.14,.02,-.1,.16,-.13,-.06,-.04,-.36)*f02+
    m4(-.13,.29,-.29,.08,1.13,.02,-.83,.32,-.32,.04,-.31,-.16,.14,-.03,-.2,.39)*f03+
    vec4<f32>(.73,-4.28,-1.56,-1.8))+f00;
    let f11=sin(m4(-1.11,.55,-.12,-1.00,.16,.15,-.3,.31,-.01,.01,.31,-.42,-.29,.38,-.04,.71)*f00+
    m4(.96,-.02,.86,.52,-.14,.6,.44,.43,.02,-.15,-.49,-.05,-.06,-.25,-.03,-.22)*f01+
    m4(.52,.44,-.05,-.11,-.56,-.1,-.61,-.4,-.04,.55,.32,-.07,-.02,.28,.26,-.49)*f02+
    m4(.02,-.32,.06,-.17,-.59,.00,-.24,.6,-.06,.13,-.21,-.27,-.12,-.14,.58,-.55)*f03+
    vec4<f32>(-2.24,-3.48,-.8,1.41))+f01;
    let f12=sin(m4(.44,-.06,-.79,-.46,.05,-.6,.3,.36,.35,.12,.02,.12,.4,-.26,.63,-.21)*f00+
    m4(-.48,.43,-.73,-.4,.11,-.01,.71,.05,-.25,.25,-.28,-.2,.32,-.02,-.84,.16)*f01+
    m4(.39,-.07,.9,.36,-.38,-.27,-1.86,-.39,.48,-.2,-.05,.1,-.00,-.21,.29,.63)*f02+
    m4(.46,-.32,.06,.09,.72,-.47,.81,.78,.9,.02,-.21,.08,-.16,.22,.32,-.13)*f03+
    vec4<f32>(3.38,1.2,.84,1.41))+f02;
    let f13=sin(m4(-.41,-.24,-.71,-.25,-.24,-.75,-.09,.02,-.27,-.42,.02,.03,-.01,.51,-.12,-1.24)*f00+
    m4(.64,.31,-1.36,.61,-.34,.11,.14,.79,.22,-.16,-.29,-.70,.02,-.37,.49,.39)*f01+
    m4(.79,.47,.54,-.47,-1.13,-.35,-1.03,-.22,-.67,-.26,.1,.21,-.07,-.73,-.11,.72)*f02+
    m4(.43,-.23,.13,.09,1.38,-.63,1.57,-.2,.39,-.14,.42,.13,-.57,-.08,-.21,.21)*f03+
    vec4<f32>(-.34,-3.28,.43,-.52))+f03;
    let f20=sin(m4(-.72,.23,-.89,.52,.38,.19,-.16,-.88,.26,-.37,.09,.63,.29,-.72,.3,-.95)*f10+
    m4(-.22,-.51,-.42,-.73,-.32,.00,-1.03,1.17,-.2,-.03,-.13,-.16,-.41,.09,.36,-.84)*f11+
    m4(-.21,.01,.33,.47,.05,.2,-.44,-1.04,.13,.12,-.13,.31,.01,-.34,.41,-.34)*f12+
    m4(-.13,-.06,-.39,-.22,.48,.25,.24,-.97,-.34,.14,.42,-.00,-.44,.05,.09,-.95)*f13+
    vec4<f32>(.48,.87,-.87,-2.06))/1.4+f10;
    let f21=sin(m4(-.27,.29,-.21,.15,.34,-.23,.85,-.09,-1.15,-.24,-.05,-.25,-.12,-.73,-.17,-.37)*f10+
    m4(-1.11,.35,-.93,-.06,-.79,-.03,-.46,-.37,.6,-.37,-.14,.45,-.03,-.21,.02,.59)*f11+
    m4(-.92,-.17,-.58,-.18,.58,.6,.83,-1.04,-.8,-.16,.23,-.11,.08,.16,.76,.61)*f12+
    m4(.29,.45,.3,.39,-.91,.66,-.35,-.35,.21,.16,-.54,-.63,1.1,-.38,.2,.15)*f13+
    vec4<f32>(-1.72,-.14,1.92,2.08))/1.4+f11;
    let f22=sin(m4(1.00,.66,1.3,-.51,.88,.25,-.67,.03,-.68,-.08,-.12,-.14,.46,1.15,.38,-.1)*f10+
    m4(.51,-.57,.41,-.09,.68,-.5,-.04,-1.01,.2,.44,-.6,.46,-.09,-.37,-1.3,.04)*f11+
    m4(.14,.29,-.45,-.06,-.65,.33,-.37,-.95,.71,-.07,1.00,-.6,-1.68,-.2,-.00,-.7)*f12+
    m4(-.31,.69,.56,.13,.95,.36,.56,.59,-.63,.52,-.3,.17,1.23,.72,.95,.75)*f13+
    vec4<f32>(-.9,-3.26,-.44,-3.11))/1.4+f12;
    let f23=sin(m4(.51,-.98,-.28,.16,-.22,-.17,-1.03,.22,.7,-.15,.12,.43,.78,.67,-.85,-.25)*f10+
    m4(.81,.6,-.89,.61,-1.03,-.33,.6,-.11,-.06,.01,-.02,-.44,.73,.69,1.02,.62)*f11+
    m4(-.1,.52,.8,-.65,.4,-.75,.47,1.56,.03,.05,.08,.31,-.03,.22,-1.63,.07)*f12+
    m4(-.18,-.07,-1.22,.48,-.01,.56,.07,.15,.24,.25,-.09,-.54,.23,-.08,.2,.36)*f13+
    vec4<f32>(-1.11,-4.28,1.02,-.23))/1.4+f13;
    return dot(f20,vec4<f32>(.09,.12,-.07,-.03))+dot(f21,vec4<f32>(-.04,.07,-.08,.05))+
    dot(f22,vec4<f32>(-.01,.06,-.02,.07))+dot(f23,vec4<f32>(-.05,.07,.03,.04))- 0.16;
    }
    ```
    <img src="https://habrastorage.org/webt/4c/kf/dw/4ckfdwujkpobfo27nn63mkwaw-4.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
  8. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 38 additions and 39 deletions.
    77 changes: 38 additions & 39 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -357,58 +357,57 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {

    #### Bunny - bound
    ```rs
    fn fmat4init(a1: f32, a2: f32, a3: f32, a4: f32, b1: f32, b2: f32, b3: f32, b4: f32,
    c1: f32, c2: f32, c3: f32, c4: f32, d1: f32, d2: f32, d3: f32, d4: f32) -> mat4x4<f32> {
    fn m4(a1: f32, a2: f32, a3: f32, a4: f32, b1: f32, b2: f32, b3: f32, b4: f32,
    c1: f32, c2: f32, c3: f32, c4: f32, d1: f32, d2: f32, d3: f32, d4: f32) -> mat4x4<f32> {
    return mat4x4<f32>(vec4<f32>(a1, a2, a3, a4), vec4<f32>(b1, b2, b3, b4),
    vec4<f32>(c1, c2, c3, c4), vec4<f32>(d1, d2, d3, d4));
    }

    fn bunny(p: vec3<f32>) -> f32 {
    if (dot(p, p) > 1.) { return length(p) - .8; }
    let q = vec4<f32>(p, 1.);
    let f00=sin(fmat4init(-3.02,1.95,-3.42,-.6,3.08,.85,-2.25,-.24,-.29,1.16,-3.74,2.89,-.71,4.5,-3.24,-3.5)*q);
    let f01=sin(fmat4init(-.4,-3.61,3.23,-.14,-.36,3.64,-3.91,2.66,2.9,-.54,-2.75,2.71,7.02,-5.41,-1.12,-7.41)*q);
    let f02=sin(fmat4init(-1.77,-1.28,-4.29,-3.2,-3.49,-2.81,-.64,2.79,3.15,2.14,-3.85,1.83,-2.07,4.49,5.33,-2.17)*q);
    let f03=sin(fmat4init(-.49,.68,3.05,.42,-2.87,.78,3.78,-3.41,-2.65,.33,.07,-.64,-3.24,-5.9,1.14,-4.71)*q);
    let f10=sin(fmat4init(-.34,.06,-.59,-.76,.1,-.19,-.12,.44,.64,-.02,-.26,.15,-.16,.21,.91,.15)*f00+
    fmat4init(.01,.54,-.77,.11,.06,-.14,.43,.51,-.18,.08,.39,.2,.33,-.49,-.1,.19)*f01+
    fmat4init(.27,.22,.43,.53,.18,-.17,.23,-.64,-.14,.02,-.1,.16,-.13,-.06,-.04,-.36)*f02+
    fmat4init(-.13,.29,-.29,.08,1.13,.02,-.83,.32,-.32,.04,-.31,-.16,.14,-.03,-.2,.39)*f03+
    let f00=sin(m4(-3.02,1.95,-3.42,-.6,3.08,.85,-2.25,-.24,-.29,1.16,-3.74,2.89,-.71,4.5,-3.24,-3.5)*q);
    let f01=sin(m4(-.4,-3.61,3.23,-.14,-.36,3.64,-3.91,2.66,2.9,-.54,-2.75,2.71,7.02,-5.41,-1.12,-7.41)*q);
    let f02=sin(m4(1.77,1.28,4.29,3.2,3.49,2.81,.64,-2.79,-3.15,-2.14,3.85,-1.83,2.07,-4.49,-5.33,2.17)*-q);
    let f03=sin(m4(-.49,.68,3.05,.42,-2.87,.78,3.78,-3.41,-2.65,.33,.07,-.64,-3.24,-5.9,1.14,-4.71)*q);
    let f10=sin(m4(-.34,.06,-.59,-.76,.1,-.19,-.12,.44,.64,-.02,-.26,.15,-.16,.21,.91,.15)*f00+
    m4(.01,.54,-.77,.11,.06,-.14,.43,.51,-.18,.08,.39,.2,.33,-.49,-.1,.19)*f01+
    m4(.27,.22,.43,.53,.18,-.17,.23,-.64,-.14,.02,-.1,.16,-.13,-.06,-.04,-.36)*f02+
    m4(-.13,.29,-.29,.08,1.13,.02,-.83,.32,-.32,.04,-.31,-.16,.14,-.03,-.2,.39)*f03+
    vec4<f32>(.73,-4.28,-1.56,-1.8))+f00;
    let f11=sin(fmat4init(-1.11,.55,-.12,-1.00,.16,.15,-.3,.31,-.01,.01,.31,-.42,-.29,.38,-.04,.71)*f00+
    fmat4init(.96,-.02,.86,.52,-.14,.6,.44,.43,.02,-.15,-.49,-.05,-.06,-.25,-.03,-.22)*f01+
    fmat4init(.52,.44,-.05,-.11,-.56,-.1,-.61,-.4,-.04,.55,.32,-.07,-.02,.28,.26,-.49)*f02+
    fmat4init(.02,-.32,.06,-.17,-.59,.00,-.24,.6,-.06,.13,-.21,-.27,-.12,-.14,.58,-.55)*f03+
    let f11=sin(m4(-1.11,.55,-.12,-1.00,.16,.15,-.3,.31,-.01,.01,.31,-.42,-.29,.38,-.04,.71)*f00+
    m4(.96,-.02,.86,.52,-.14,.6,.44,.43,.02,-.15,-.49,-.05,-.06,-.25,-.03,-.22)*f01+
    m4(.52,.44,-.05,-.11,-.56,-.1,-.61,-.4,-.04,.55,.32,-.07,-.02,.28,.26,-.49)*f02+
    m4(.02,-.32,.06,-.17,-.59,.00,-.24,.6,-.06,.13,-.21,-.27,-.12,-.14,.58,-.55)*f03+
    vec4<f32>(-2.24,-3.48,-.8,1.41))+f01;
    let f12=sin(fmat4init(.44,-.06,-.79,-.46,.05,-.6,.3,.36,.35,.12,.02,.12,.4,-.26,.63,-.21)*f00+
    fmat4init(-.48,.43,-.73,-.4,.11,-.01,.71,.05,-.25,.25,-.28,-.2,.32,-.02,-.84,.16)*f01+
    fmat4init(.39,-.07,.9,.36,-.38,-.27,-1.86,-.39,.48,-.2,-.05,.1,-.00,-.21,.29,.63)*f02+
    fmat4init(.46,-.32,.06,.09,.72,-.47,.81,.78,.9,.02,-.21,.08,-.16,.22,.32,-.13)*f03+
    let f12=sin(m4(.44,-.06,-.79,-.46,.05,-.6,.3,.36,.35,.12,.02,.12,.4,-.26,.63,-.21)*f00+
    m4(-.48,.43,-.73,-.4,.11,-.01,.71,.05,-.25,.25,-.28,-.2,.32,-.02,-.84,.16)*f01+
    m4(.39,-.07,.9,.36,-.38,-.27,-1.86,-.39,.48,-.2,-.05,.1,-.00,-.21,.29,.63)*f02+
    m4(.46,-.32,.06,.09,.72,-.47,.81,.78,.9,.02,-.21,.08,-.16,.22,.32,-.13)*f03+
    vec4<f32>(3.38,1.2,.84,1.41))+f02;
    let f13=sin(fmat4init(-.41,-.24,-.71,-.25,-.24,-.75,-.09,.02,-.27,-.42,.02,.03,-.01,.51,-.12,-1.24)*f00+
    fmat4init(.64,.31,-1.36,.61,-.34,.11,.14,.79,.22,-.16,-.29,-.70,.02,-.37,.49,.39)*f01+
    fmat4init(.79,.47,.54,-.47,-1.13,-.35,-1.03,-.22,-.67,-.26,.1,.21,-.07,-.73,-.11,.72)*f02+
    fmat4init(.43,-.23,.13,.09,1.38,-.63,1.57,-.2,.39,-.14,.42,.13,-.57,-.08,-.21,.21)*f03+
    let f13=sin(m4(-.41,-.24,-.71,-.25,-.24,-.75,-.09,.02,-.27,-.42,.02,.03,-.01,.51,-.12,-1.24)*f00+
    m4(.64,.31,-1.36,.61,-.34,.11,.14,.79,.22,-.16,-.29,-.70,.02,-.37,.49,.39)*f01+
    m4(.79,.47,.54,-.47,-1.13,-.35,-1.03,-.22,-.67,-.26,.1,.21,-.07,-.73,-.11,.72)*f02+
    m4(.43,-.23,.13,.09,1.38,-.63,1.57,-.2,.39,-.14,.42,.13,-.57,-.08,-.21,.21)*f03+
    vec4<f32>(-.34,-3.28,.43,-.52))+f03;
    let f20=sin(fmat4init(-.72,.23,-.89,.52,.38,.19,-.16,-.88,.26,-.37,.09,.63,.29,-.72,.3,-.95)*f10+
    fmat4init(-.22,-.51,-.42,-.73,-.32,.00,-1.03,1.17,-.2,-.03,-.13,-.16,-.41,.09,.36,-.84)*f11+
    fmat4init(-.21,.01,.33,.47,.05,.2,-.44,-1.04,.13,.12,-.13,.31,.01,-.34,.41,-.34)*f12+
    fmat4init(-.13,-.06,-.39,-.22,.48,.25,.24,-.97,-.34,.14,.42,-.00,-.44,.05,.09,-.95)*f13+
    let f20=sin(m4(-.72,.23,-.89,.52,.38,.19,-.16,-.88,.26,-.37,.09,.63,.29,-.72,.3,-.95)*f10+
    m4(-.22,-.51,-.42,-.73,-.32,.00,-1.03,1.17,-.2,-.03,-.13,-.16,-.41,.09,.36,-.84)*f11+
    m4(-.21,.01,.33,.47,.05,.2,-.44,-1.04,.13,.12,-.13,.31,.01,-.34,.41,-.34)*f12+
    m4(-.13,-.06,-.39,-.22,.48,.25,.24,-.97,-.34,.14,.42,-.00,-.44,.05,.09,-.95)*f13+
    vec4<f32>(.48,.87,-.87,-2.06))/1.4+f10;
    let f21=sin(fmat4init(-.27,.29,-.21,.15,.34,-.23,.85,-.09,-1.15,-.24,-.05,-.25,-.12,-.73,-.17,-.37)*f10+
    fmat4init(-1.11,.35,-.93,-.06,-.79,-.03,-.46,-.37,.6,-.37,-.14,.45,-.03,-.21,.02,.59)*f11+
    fmat4init(-.92,-.17,-.58,-.18,.58,.6,.83,-1.04,-.8,-.16,.23,-.11,.08,.16,.76,.61)*f12+
    fmat4init(.29,.45,.3,.39,-.91,.66,-.35,-.35,.21,.16,-.54,-.63,1.1,-.38,.2,.15)*f13+
    let f21=sin(m4(-.27,.29,-.21,.15,.34,-.23,.85,-.09,-1.15,-.24,-.05,-.25,-.12,-.73,-.17,-.37)*f10+
    m4(-1.11,.35,-.93,-.06,-.79,-.03,-.46,-.37,.6,-.37,-.14,.45,-.03,-.21,.02,.59)*f11+
    m4(-.92,-.17,-.58,-.18,.58,.6,.83,-1.04,-.8,-.16,.23,-.11,.08,.16,.76,.61)*f12+
    m4(.29,.45,.3,.39,-.91,.66,-.35,-.35,.21,.16,-.54,-.63,1.1,-.38,.2,.15)*f13+
    vec4<f32>(-1.72,-.14,1.92,2.08))/1.4+f11;
    let f22=sin(fmat4init(1.00,.66,1.3,-.51,.88,.25,-.67,.03,-.68,-.08,-.12,-.14,.46,1.15,.38,-.1)*f10+
    fmat4init(.51,-.57,.41,-.09,.68,-.5,-.04,-1.01,.2,.44,-.6,.46,-.09,-.37,-1.3,.04)*f11+
    fmat4init(.14,.29,-.45,-.06,-.65,.33,-.37,-.95,.71,-.07,1.00,-.6,-1.68,-.2,-.00,-.7)*f12+
    fmat4init(-.31,.69,.56,.13,.95,.36,.56,.59,-.63,.52,-.3,.17,1.23,.72,.95,.75)*f13+
    let f22=sin(m4(1.00,.66,1.3,-.51,.88,.25,-.67,.03,-.68,-.08,-.12,-.14,.46,1.15,.38,-.1)*f10+
    m4(.51,-.57,.41,-.09,.68,-.5,-.04,-1.01,.2,.44,-.6,.46,-.09,-.37,-1.3,.04)*f11+
    m4(.14,.29,-.45,-.06,-.65,.33,-.37,-.95,.71,-.07,1.00,-.6,-1.68,-.2,-.00,-.7)*f12+
    m4(-.31,.69,.56,.13,.95,.36,.56,.59,-.63,.52,-.3,.17,1.23,.72,.95,.75)*f13+
    vec4<f32>(-.9,-3.26,-.44,-3.11))/1.4+f12;
    let f23=sin(fmat4init(.51,-.98,-.28,.16,-.22,-.17,-1.03,.22,.7,-.15,.12,.43,.78,.67,-.85,-.25)*f10+
    fmat4init(.81,.6,-.89,.61,-1.03,-.33,.6,-.11,-.06,.01,-.02,-.44,.73,.69,1.02,.62)*f11+
    fmat4init(-.1,.52,.8,-.65,.4,-.75,.47,1.56,.03,.05,.08,.31,-.03,.22,-1.63,.07)*f12+
    fmat4init(-.18,-.07,-1.22,.48,-.01,.56,.07,.15,.24,.25,-.09,-.54,.23,-.08,.2,.36)*f13+
    let f23=sin(m4(.51,-.98,-.28,.16,-.22,-.17,-1.03,.22,.7,-.15,.12,.43,.78,.67,-.85,-.25)*f10+
    m4(.81,.6,-.89,.61,-1.03,-.33,.6,-.11,-.06,.01,-.02,-.44,.73,.69,1.02,.62)*f11+
    m4(-.1,.52,.8,-.65,.4,-.75,.47,1.56,.03,.05,.08,.31,-.03,.22,-1.63,.07)*f12+
    m4(-.18,-.07,-1.22,.48,-.01,.56,.07,.15,.24,.25,-.09,-.54,.23,-.08,.2,.36)*f13+
    vec4<f32>(-1.11,-4.28,1.02,-.23))/1.4+f13;
    return dot(f20,vec4<f32>(.09,.12,-.07,-.03))+dot(f21,vec4<f32>(-.04,.07,-.08,.05))+
    dot(f22,vec4<f32>(-.01,.06,-.02,.07))+dot(f23,vec4<f32>(-.05,.07,.03,.04))- 0.16;
  9. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 61 additions and 0 deletions.
    61 changes: 61 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -355,6 +355,67 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px">

    #### Bunny - bound
    ```rs
    fn fmat4init(a1: f32, a2: f32, a3: f32, a4: f32, b1: f32, b2: f32, b3: f32, b4: f32,
    c1: f32, c2: f32, c3: f32, c4: f32, d1: f32, d2: f32, d3: f32, d4: f32) -> mat4x4<f32> {
    return mat4x4<f32>(vec4<f32>(a1, a2, a3, a4), vec4<f32>(b1, b2, b3, b4),
    vec4<f32>(c1, c2, c3, c4), vec4<f32>(d1, d2, d3, d4));
    }

    fn bunny(p: vec3<f32>) -> f32 {
    if (dot(p, p) > 1.) { return length(p) - .8; }
    let q = vec4<f32>(p, 1.);
    let f00=sin(fmat4init(-3.02,1.95,-3.42,-.6,3.08,.85,-2.25,-.24,-.29,1.16,-3.74,2.89,-.71,4.5,-3.24,-3.5)*q);
    let f01=sin(fmat4init(-.4,-3.61,3.23,-.14,-.36,3.64,-3.91,2.66,2.9,-.54,-2.75,2.71,7.02,-5.41,-1.12,-7.41)*q);
    let f02=sin(fmat4init(-1.77,-1.28,-4.29,-3.2,-3.49,-2.81,-.64,2.79,3.15,2.14,-3.85,1.83,-2.07,4.49,5.33,-2.17)*q);
    let f03=sin(fmat4init(-.49,.68,3.05,.42,-2.87,.78,3.78,-3.41,-2.65,.33,.07,-.64,-3.24,-5.9,1.14,-4.71)*q);
    let f10=sin(fmat4init(-.34,.06,-.59,-.76,.1,-.19,-.12,.44,.64,-.02,-.26,.15,-.16,.21,.91,.15)*f00+
    fmat4init(.01,.54,-.77,.11,.06,-.14,.43,.51,-.18,.08,.39,.2,.33,-.49,-.1,.19)*f01+
    fmat4init(.27,.22,.43,.53,.18,-.17,.23,-.64,-.14,.02,-.1,.16,-.13,-.06,-.04,-.36)*f02+
    fmat4init(-.13,.29,-.29,.08,1.13,.02,-.83,.32,-.32,.04,-.31,-.16,.14,-.03,-.2,.39)*f03+
    vec4<f32>(.73,-4.28,-1.56,-1.8))+f00;
    let f11=sin(fmat4init(-1.11,.55,-.12,-1.00,.16,.15,-.3,.31,-.01,.01,.31,-.42,-.29,.38,-.04,.71)*f00+
    fmat4init(.96,-.02,.86,.52,-.14,.6,.44,.43,.02,-.15,-.49,-.05,-.06,-.25,-.03,-.22)*f01+
    fmat4init(.52,.44,-.05,-.11,-.56,-.1,-.61,-.4,-.04,.55,.32,-.07,-.02,.28,.26,-.49)*f02+
    fmat4init(.02,-.32,.06,-.17,-.59,.00,-.24,.6,-.06,.13,-.21,-.27,-.12,-.14,.58,-.55)*f03+
    vec4<f32>(-2.24,-3.48,-.8,1.41))+f01;
    let f12=sin(fmat4init(.44,-.06,-.79,-.46,.05,-.6,.3,.36,.35,.12,.02,.12,.4,-.26,.63,-.21)*f00+
    fmat4init(-.48,.43,-.73,-.4,.11,-.01,.71,.05,-.25,.25,-.28,-.2,.32,-.02,-.84,.16)*f01+
    fmat4init(.39,-.07,.9,.36,-.38,-.27,-1.86,-.39,.48,-.2,-.05,.1,-.00,-.21,.29,.63)*f02+
    fmat4init(.46,-.32,.06,.09,.72,-.47,.81,.78,.9,.02,-.21,.08,-.16,.22,.32,-.13)*f03+
    vec4<f32>(3.38,1.2,.84,1.41))+f02;
    let f13=sin(fmat4init(-.41,-.24,-.71,-.25,-.24,-.75,-.09,.02,-.27,-.42,.02,.03,-.01,.51,-.12,-1.24)*f00+
    fmat4init(.64,.31,-1.36,.61,-.34,.11,.14,.79,.22,-.16,-.29,-.70,.02,-.37,.49,.39)*f01+
    fmat4init(.79,.47,.54,-.47,-1.13,-.35,-1.03,-.22,-.67,-.26,.1,.21,-.07,-.73,-.11,.72)*f02+
    fmat4init(.43,-.23,.13,.09,1.38,-.63,1.57,-.2,.39,-.14,.42,.13,-.57,-.08,-.21,.21)*f03+
    vec4<f32>(-.34,-3.28,.43,-.52))+f03;
    let f20=sin(fmat4init(-.72,.23,-.89,.52,.38,.19,-.16,-.88,.26,-.37,.09,.63,.29,-.72,.3,-.95)*f10+
    fmat4init(-.22,-.51,-.42,-.73,-.32,.00,-1.03,1.17,-.2,-.03,-.13,-.16,-.41,.09,.36,-.84)*f11+
    fmat4init(-.21,.01,.33,.47,.05,.2,-.44,-1.04,.13,.12,-.13,.31,.01,-.34,.41,-.34)*f12+
    fmat4init(-.13,-.06,-.39,-.22,.48,.25,.24,-.97,-.34,.14,.42,-.00,-.44,.05,.09,-.95)*f13+
    vec4<f32>(.48,.87,-.87,-2.06))/1.4+f10;
    let f21=sin(fmat4init(-.27,.29,-.21,.15,.34,-.23,.85,-.09,-1.15,-.24,-.05,-.25,-.12,-.73,-.17,-.37)*f10+
    fmat4init(-1.11,.35,-.93,-.06,-.79,-.03,-.46,-.37,.6,-.37,-.14,.45,-.03,-.21,.02,.59)*f11+
    fmat4init(-.92,-.17,-.58,-.18,.58,.6,.83,-1.04,-.8,-.16,.23,-.11,.08,.16,.76,.61)*f12+
    fmat4init(.29,.45,.3,.39,-.91,.66,-.35,-.35,.21,.16,-.54,-.63,1.1,-.38,.2,.15)*f13+
    vec4<f32>(-1.72,-.14,1.92,2.08))/1.4+f11;
    let f22=sin(fmat4init(1.00,.66,1.3,-.51,.88,.25,-.67,.03,-.68,-.08,-.12,-.14,.46,1.15,.38,-.1)*f10+
    fmat4init(.51,-.57,.41,-.09,.68,-.5,-.04,-1.01,.2,.44,-.6,.46,-.09,-.37,-1.3,.04)*f11+
    fmat4init(.14,.29,-.45,-.06,-.65,.33,-.37,-.95,.71,-.07,1.00,-.6,-1.68,-.2,-.00,-.7)*f12+
    fmat4init(-.31,.69,.56,.13,.95,.36,.56,.59,-.63,.52,-.3,.17,1.23,.72,.95,.75)*f13+
    vec4<f32>(-.9,-3.26,-.44,-3.11))/1.4+f12;
    let f23=sin(fmat4init(.51,-.98,-.28,.16,-.22,-.17,-1.03,.22,.7,-.15,.12,.43,.78,.67,-.85,-.25)*f10+
    fmat4init(.81,.6,-.89,.61,-1.03,-.33,.6,-.11,-.06,.01,-.02,-.44,.73,.69,1.02,.62)*f11+
    fmat4init(-.1,.52,.8,-.65,.4,-.75,.47,1.56,.03,.05,.08,.31,-.03,.22,-1.63,.07)*f12+
    fmat4init(-.18,-.07,-1.22,.48,-.01,.56,.07,.15,.24,.25,-.09,-.54,.23,-.08,.2,.36)*f13+
    vec4<f32>(-1.11,-4.28,1.02,-.23))/1.4+f13;
    return dot(f20,vec4<f32>(.09,.12,-.07,-.03))+dot(f21,vec4<f32>(-.04,.07,-.08,.05))+
    dot(f22,vec4<f32>(-.01,.06,-.02,.07))+dot(f23,vec4<f32>(-.05,.07,.03,.04))- 0.16;
    }
    ```
    <img src="https://habrastorage.org/webt/4c/kf/dw/4ckfdwujkpobfo27nn63mkwaw-4.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
  10. @munrocket munrocket revised this gist Jul 21, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -625,5 +625,6 @@ fn length8(p: vec3<f32>) -> f32 {
    return pow(q.x + q.y + q.z, 1. / 8.);
    }
    ```
    <img src="https://habrastorage.org/webt/uw/dm/oz/uwdmozwn25o_dpcdlsrdb-ppevm.jpeg" width="150px"/>

    MIT License. © 2020 Munrocket, Inigo Quilez, Johann Korndörfer, Martijn Steinrucken, Blackle Mori
  11. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    # 3D SDF Primitives in WGSL

    #### How to use this gist:
    1. Build a sphere tracer with WebGPU ([paper](https://www.researchgate.net/publication/2792108_Sphere_Tracing_A_Geometric_Method_for_the_Antialiased_Ray_Tracing_of_Implicit_Surfaces), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
    1. Build a sphere tracer with WebGPU ([paper](https://www.researchgate.net/publication/2792108_Sphere_Tracing_A_Geometric_Method_for_the_Antialiased_Ray_Tracing_of_Implicit_Surfaces), [paper2](https://www.semanticscholar.org/paper/Enhanced-Sphere-Tracing-Keinert-Sch%C3%A4fer/4c9bd91bd044980f5746d623315be5285cc799c9), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
    2. Create model with sdf functions from here
    3. Add light and shadows
    4. ???
    @@ -624,4 +624,6 @@ fn length8(p: vec3<f32>) -> f32 {
    q = q * q; q = q * q;
    return pow(q.x + q.y + q.z, 1. / 8.);
    }
    ```
    ```

    MIT License. © 2020 Munrocket, Inigo Quilez, Johann Korndörfer, Martijn Steinrucken, Blackle Mori
  12. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -66,7 +66,7 @@ fn sdGyroid(p: vec3<f32>, h: f32) -> f32 {
    return abs(dot(sin(p), cos(p.zxy))) - h;
    }
    ```
    <img src="https://habrastorage.org/webt/q9/1v/ck/q91vckssijkyduknwph_sdg2upu.jpeg" width="150px">
    <img src="https://habrastorage.org/webt/nu/mi/v9/numiv9d7cz6dfxrnkgripzbbai4.jpeg" width="150px">

    #### Torus - exact
    ```rs
  13. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -60,6 +60,14 @@ fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px">

    #### Gyroid - bound
    ```rs
    fn sdGyroid(p: vec3<f32>, h: f32) -> f32 {
    return abs(dot(sin(p), cos(p.zxy))) - h;
    }
    ```
    <img src="https://habrastorage.org/webt/q9/1v/ck/q91vckssijkyduknwph_sdg2upu.jpeg" width="150px">

    #### Torus - exact
    ```rs
    fn sdTorus(p: vec3<f32>, R: f32, r: f32) -> f32 {
  14. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 7 additions and 4 deletions.
    11 changes: 7 additions & 4 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -576,7 +576,7 @@ fn opOnion(d: f32, thickness: f32) -> f32 {
    }
    //let d = opOnion(sdfPrimitive3d(p), thickness);
    ```
    <img src="https://habrastorage.org/webt/ud/q5/yj/udq5yjrfmqa2kx_jdl2pcpkri_0.jpeg" width="150px"/>
    <img src="https://habrastorage.org/webt/ja/q9/i0/jaq9i0oqkmdtzya0j9ewyntmth8.jpeg" width="150px"/>

    #### Extrusion from 2D SDF - exact
    ```rs
    @@ -586,6 +586,7 @@ fn opExtrusion(d: f32, z: f32, h: f32) -> f32 {
    }
    //let d = opExtrusion(sdfPrimitive2d(p.xy), p.z, h));
    ```
    <img src="https://habrastorage.org/webt/u_/zq/pm/u_zqpmkpzepemz5fthwhx4f0zy8.jpeg" width="150px"/>

    #### Revolution from 2D SDF - exact
    ```rs
    @@ -594,12 +595,14 @@ fn opRevolution(p: vec3<f32>, o: f32) -> vec2<f32> {
    }
    //let d = sdfPrimitive2d(opRevolution(p, h));
    ```
    <img src="https://habrastorage.org/webt/qd/bn/kw/qdbnkwkkjuqqemdqm-knf5ov53c.jpeg" width="150px"/>

    #### Change metric - bound
    ```rs
    fn length2(p: vec3<f32>) -> f32 {
    let q = p * p;
    return sqrt(q.x + q.y + q.z);
    fn length4(p: vec3<f32>) -> f32 {
    var q: vec3<f32> = p * p;
    q = q * q;
    return sqrt(sqrt(q.x + q.y + q.z));
    }

    fn length6(p: vec3<f32>) -> f32 {
  15. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -559,14 +559,15 @@ fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> vec4<f32> {
    //let p2 = opElongateCorrect(p, h);
    //let d = p2.w + sdfPrimitive3d(p2.xyz);
    ```
    <img src="https://habrastorage.org/webt/dq/dp/rp/dqdprp7qpuiet6dx5wcwkpbnfbe.jpeg" width="150px"/>
    <img src="https://habrastorage.org/webt/qn/s4/t-/qns4t-dr6gdwdzedebd_ohbsy-a.png" width="150px"/>

    #### Rounding - exact
    ```rs
    fn opRound(p: vec3<f32>, r: f32) -> f32 {
    return sdfPrimitive3d(p) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/qt/mc/m7/qtmcm7tvpvidagqxnttvbluobbc.jpeg" width="150px"/>

    #### Onion - exact
    ```rs
    @@ -575,6 +576,7 @@ fn opOnion(d: f32, thickness: f32) -> f32 {
    }
    //let d = opOnion(sdfPrimitive3d(p), thickness);
    ```
    <img src="https://habrastorage.org/webt/ud/q5/yj/udq5yjrfmqa2kx_jdl2pcpkri_0.jpeg" width="150px"/>

    #### Extrusion from 2D SDF - exact
    ```rs
  16. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 22 additions and 75 deletions.
    97 changes: 22 additions & 75 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -347,50 +347,6 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px">

    #### Triangle - exact
    ```rs
    fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    let cb = c - b; let pb = p - b;
    let ac = a - c; let pc = p - c;
    let nor = cross(ba, ac);

    let d1 = ba * clamp(dot(ba, pa) / dot(ba, ba), 0., 1.) - pa;
    let d2 = cb * clamp(dot(cb, pb) / dot(cb, cb), 0., 1.) - pb;
    let d3 = ac * clamp(dot(ac, pc) / dot(ac, ac), 0., 1.) - pc;

    let k0 = min(min(dot(d1, d1), dot(d2, d2)), dot(d3, d3));
    let k1 = dot(nor, pa) * dot(nor, pa) / dot(nor, nor);
    let t = sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) +
    sign(dot(cross(ac, nor), pc));
    return sqrt(select(k0, k1, t < 2.));
    }
    ```
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px">

    #### Quad - exact
    ```rs
    fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    let cb = c - b; let pb = p - b;
    let dc = d - c; let pc = p - c;
    let ad = a - d; let pd = p - d;
    let nor = cross(ba, ad);

    let d1 = ba * clamp(dot(ba, pa) / dot(ba, ba), 0., 1.) - pa;
    let d2 = cb * clamp(dot(cb, pb) / dot(cb, cb), 0., 1.) - pb;
    let d3 = dc * clamp(dot(dc, pc) / dot(dc, dc), 0., 1.) - pc;
    let d4 = ad * clamp(dot(ad, pd) / dot(ad, ad), 0., 1.) - pd;

    let k0 = min(min(dot(d1, d1), dot(d2, d2)), min(dot(d3, d3), dot(d4, d4)));
    let k1 = dot(nor, pa) * dot(nor, pa) / dot(nor, nor);
    let t = sign(dot(cross(ba, nor), pa)) + sign(dot(cross(cb, nor), pb)) +
    sign(dot(cross(dc, nor), pc)) + sign(dot(cross(ad, nor), pd));
    return sqrt(select(k0, k1, t < 3.));
    }
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
    @@ -406,38 +362,19 @@ fn opIntersection(d1: f32, d2: f32) -> f32 { return max(d1, d2); }
    #### Chamfer Union, Chamfer Subtraction, Chamfer Intersection - bound, bound, bound
    ```rs
    fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * sqrt(0.5));
    return min(min(d1, d2), (d1 - r + d2) * 0.5);
    }

    fn opSubtractionChamfer(a: f32, b: f32, r: f32) -> f32{
    return max(max(a, -b), (a + r - b) * sqrt(0.5));
    fn opSubtractionChamfer(d1: f32, d2: f32, r: f32) -> f32{
    return max(max(d1, -d2), (d1 + r - d2) * 0.5);
    }

    fn opIntersectionChamfer(a: f32, b: f32, r: f32) -> f32 {
    return max(max(a, b), (a + r + b) * sqrt(0.5));
    fn opIntersectionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return max(max(d1, d2), (d1 + r + d2) * 0.5);
    }
    ```
    <img src="https://habrastorage.org/webt/tg/vq/jr/tgvqjr32gtadua4rib-fvfxz4ta.jpeg" width="450px">

    #### Round Union, Round Subtraction, Round Intersection - bound, bound, bound
    ```rs
    fn opUnionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r - a, r - b), vec2<f32>(0.));
    return max(r, min(a, b)) - length(u);
    }

    fn opSubtractionRound (a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r + a, r - b), vec2<f32>(0.));
    return min(-r, max(a, -b)) + length(u);
    }

    fn opIntersectionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r + a, r + b), vec2<f32>(0.));
    return min(-r, max(a, b)) + length(u);
    }
    ```
    <img src="https://habrastorage.org/webt/th/2z/xx/th2zxxyqqjohcut6ospfu69bqpw.jpeg" width="450px">

    #### Blend Union, Blend Subtraction, Blend Intersection - bound, bound, bound
    ```rs
    fn opUnionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    @@ -473,7 +410,7 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {
    fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.y);
    let c = cos(k * p.y);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    let m = mat2x2<f32>(vec2<f32>(c, s), vec2<f32>(-s, c));
    return vec3<f32>(m * p.xz, p.y);
    }
    //let d = sdfPrimitive3d(opTwist(p, k));
    @@ -499,6 +436,7 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    fn opTranslate(p: vec3<f32>, t: vec3<f32>) -> vec3<f32> {
    return p - t;
    }
    //let d = sdfPrimitive3d(opTranslate(p, t));
    ```
    <img src="https://habrastorage.org/webt/17/20/f7/1720f7wtpzfovqvjrabg4q6qnxu.jpeg" width="150px">

    @@ -573,8 +511,14 @@ fn opTransform(p: vec3<f32>, transform: mat4x4<f32>) -> vec3<f32> {

    #### Symmetry - exact
    ```rs
    fn opSymmetryX(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(abs(p.x), p.y, p.z);
    fn opSymmetryX(p: vec3<f32>) -> vec3<f32> { return vec3<f32>(abs(p.x), p.y, p.z); }

    fn opSymmetryY(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.x, abs(p.y), p.z);
    }

    fn opSymmetryZ(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.x, p.y, abs(p.z));
    }
    //let d = sdfPrimitive3d(opSymmetryX(p));
    ```
    @@ -587,6 +531,7 @@ fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opInfArray(p, c));
    ```
    <img src="https://habrastorage.org/webt/ly/rj/qv/lyrjqv0xen70howypmxqqprxkyq.jpeg" width="150px"/>

    #### Finite Repetition - exact
    ```rs
    @@ -595,24 +540,26 @@ fn opLimArray(p: vec3<f32>, c: f32, lim: vec3<f32>) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opLimArray(p, c));
    ```
    <img src="https://habrastorage.org/webt/uo/ii/6f/uoii6fmdcwpacdag8ld88zuu7ne.jpeg" width="150px"/>

    # Primitive alterations

    #### Elongation - exact
    ```rs
    fn opElongateFast(p: vec3<f32>, h: vec3<f32>) -> vec3<f32> {
    fn opElongate(p: vec3<f32>, h: vec3<f32>) -> vec3<f32> {
    return p - clamp(p, -h, h);
    }
    //let d = sdfPrimitive3d(opElongateFast(p, h));

    fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> vec4<f32> {
    let p2 = abs(p) - h;
    let c = min(max(p2.x, max(p2.y, p2.z)), 0.);
    return vec4<f32>(max(p2, vec3<f32>(0.)), c);
    let q = abs(p) - h;
    let sgn = 2. * step(vec3<f32>(0.), p) - vec3<f32>(1.);
    return vec4<f32>(sgn * max(q, vec3<f32>(0.)), min(max(q.x, max(q.y, q.z)), 0.));
    }
    //let p2 = opElongateCorrect(p, h);
    //let d = p2.w + sdfPrimitive3d(p2.xyz);
    ```
    <img src="https://habrastorage.org/webt/dq/dp/rp/dqdprp7qpuiet6dx5wcwkpbnfbe.jpeg" width="150px"/>

    #### Rounding - exact
    ```rs
  17. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -500,6 +500,7 @@ fn opTranslate(p: vec3<f32>, t: vec3<f32>) -> vec3<f32> {
    return p - t;
    }
    ```
    <img src="https://habrastorage.org/webt/17/20/f7/1720f7wtpzfovqvjrabg4q6qnxu.jpeg" width="150px">

    #### 90 degree rotation - exact
    ```rs
    @@ -537,6 +538,7 @@ fn opRotateZ(p: vec3<f32>, a: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opRotateY(p, a));
    ```
    <img src="https://habrastorage.org/webt/7h/he/pa/7hhepatlqmihfu7qy8xzkcx5udm.jpeg" width="150px"/>

    #### Rotation around free axis - exact
    ```rs
  18. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -455,7 +455,7 @@ fn opIntersectionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    ```
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px">
    <img src="https://habrastorage.org/webt/z_/l0/4g/z_l04gv-0rvvjbfj1gwflukjdqs.jpeg" width="450px">

    # Displacement

  19. @munrocket munrocket revised this gist Jul 19, 2021. 1 changed file with 43 additions and 12 deletions.
    55 changes: 43 additions & 12 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -494,32 +494,59 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {

    # Positioning

    #### 90 degree Oz rotation - exact
    #### Translate - exact
    ```rs
    fn opTranslate(p: vec3<f32>, t: vec3<f32>) -> vec3<f32> {
    return p - t;
    }
    ```

    #### 90 degree rotation - exact
    ```rs
    fn op90RotateX(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.x, p.z, -p.y);
    }

    fn op90RotateY(p: vec3<f32>) -> vec3<f32> {
    let r = sqrt(0.5);
    return vec3<f32>(-p.z, p.y, p.x);
    }
    //let d = sdfPrimitive3d(op90RotateY(p));

    fn op90RotateZ(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.y, -p.x, p.z);
    }
    //let d = sdfPrimitive3d(op90RotateZ(p));
    ```
    <img src="https://habrastorage.org/webt/7h/he/pa/7hhepatlqmihfu7qy8xzkcx5udm.jpeg" width="150px"/>

    #### Rotation - exact
    #### Rotation around axis - exact
    ```rs
    fn opRotateX(p: vec3<f32>, a: f32) -> vec3<f32> {
    let s = sin(a); let c = cos(a);
    return vec3<f32>(p.x, c * p.y + s * p.z, -s * p.y + c * p.z);
    }

    fn opRotateY(p: vec3<f32>, a: f32) -> vec3<f32> {
    let s = sin(a);
    let c = cos(a);
    let s = sin(a); let c = cos(a);
    return vec3<f32>(c * p.x - s * p.z, p.y, s * p.x + c * p.z);
    }

    fn opRotateZ(p: vec3<f32>, a: f32) -> vec3<f32> {
    let s = sin(a); let c = cos(a);
    return vec3<f32>(c * p.x + s * p.y, -s * p.x + c * p.y, p.z);
    }
    //let d = sdfPrimitive3d(opRotateY(p, a));
    ```

    fn opRotateYSC(p: vec3<f32>, sincos: vec2<f32>) -> vec3<f32> {
    let px = sincos[1] * p.x - sincos[0] * p.y;
    let py = sincos[0] * p.x + sincos[1] * p.y;
    return vec3<f32>(px, py, p.z);
    #### Rotation around free axis - exact
    ```rs
    fn opRotateE(p: vec3<f32>, e: vec3<f32>, a: f32) -> vec3<f32> {
    let c = cos(a);
    return dot(e, p) * (1. - c) * e - cross(e, p) * sin(a) + c * p;
    }
    //let d = sdfPrimitive3d(opRotateYSC(p, sincos));
    //let d = sdfPrimitive3d(opRotateE(p, normalize(vec3<f32>(1.,0.,.5)), a));
    ```
    <img src="https://habrastorage.org/webt/-g/7v/84/-g7v84kx6usdkgfa-6ye_kcxwfs.jpeg" width="150px"/>
    <img src="https://habrastorage.org/webt/dj/ho/sc/djhoscnd2urd2envmjtplgdna7k.jpeg" width="150px"/>

    #### Scale - exact
    ```rs
    @@ -530,13 +557,17 @@ fn opScale(p: vec3<f32>, s: f32) -> vec3<f32> {
    ```
    <img src="https://habrastorage.org/webt/p7/ex/r8/p7exr8rg5swkkvofqlgmh4stice.jpeg" width="150px"/>

    #### Free rotation/translation - exact
    #### Free transformation - exact
    ```rs
    fn opTransform(p: vec3<f32>, transform: mat4x4<f32>) -> vec3<f32> {
    let q = inverse(transform) * vec4<f32>(p, 1.);
    }
    //let d = sdfPrimitive3d(opTransform(p, transform)) * determinant(transform);

    // OR
    //let d = sdfPrimitive3d(opScale(opRotateE(opTranslate(p, t), e, a), s)) * s;
    ```
    <img src="https://habrastorage.org/webt/fp/ub/1x/fpub1xcyvy-mve7l2wvehuk4vym.jpeg" width="150px"/>

    #### Symmetry - exact
    ```rs
  20. @munrocket munrocket revised this gist Jul 18, 2021. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -503,7 +503,7 @@ fn op90RotateY(p: vec3<f32>) -> vec3<f32> {
    ```
    <img src="https://habrastorage.org/webt/7h/he/pa/7hhepatlqmihfu7qy8xzkcx5udm.jpeg" width="150px"/>

    #### Oz rotation - exact
    #### Rotation - exact
    ```rs
    fn opRotateY(p: vec3<f32>, a: f32) -> vec3<f32> {
    let s = sin(a);
    @@ -545,6 +545,7 @@ fn opSymmetryX(p: vec3<f32>) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opSymmetryX(p));
    ```
    <img src="https://habrastorage.org/webt/fp/13/-t/fp13-tocnb3scya_3g_jx7h1s5w.jpeg" width="150px"/>

    #### Infinite Repetition - exact
    ```rs
  21. @munrocket munrocket revised this gist Jul 18, 2021. 1 changed file with 16 additions and 5 deletions.
    21 changes: 16 additions & 5 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -496,20 +496,30 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {

    #### 90 degree Oz rotation - exact
    ```rs
    fn op90RotateZ(p: vec3<f32>) -> vec3<f32> {
    fn op90RotateY(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(-p.z, p.y, p.x);
    }
    //let d = sdfPrimitive3d(op90RotateZ(p));
    //let d = sdfPrimitive3d(op90RotateY(p));
    ```
    <img src="https://habrastorage.org/webt/7h/he/pa/7hhepatlqmihfu7qy8xzkcx5udm.jpeg" width="150px"/>

    #### Oz rotation - exact
    ```rs
    fn opRotateZ(p: vec3<f32>, sincos: vec2<f32>) -> vec3<f32> {
    return vec3<f32>(sincos[1] * p.x + sincos[0] * p.y, -sincos[0] * p.x + sincos[1] * p.y, p.z);
    fn opRotateY(p: vec3<f32>, a: f32) -> vec3<f32> {
    let s = sin(a);
    let c = cos(a);
    return vec3<f32>(c * p.x - s * p.z, p.y, s * p.x + c * p.z);
    }
    //let d = sdfPrimitive3d(op90RotateZ(p, sincos));
    //let d = sdfPrimitive3d(opRotateY(p, a));

    fn opRotateYSC(p: vec3<f32>, sincos: vec2<f32>) -> vec3<f32> {
    let px = sincos[1] * p.x - sincos[0] * p.y;
    let py = sincos[0] * p.x + sincos[1] * p.y;
    return vec3<f32>(px, py, p.z);
    }
    //let d = sdfPrimitive3d(opRotateYSC(p, sincos));
    ```
    <img src="https://habrastorage.org/webt/-g/7v/84/-g7v84kx6usdkgfa-6ye_kcxwfs.jpeg" width="150px"/>

    #### Scale - exact
    ```rs
    @@ -518,6 +528,7 @@ fn opScale(p: vec3<f32>, s: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opScale(p, s)) * s;
    ```
    <img src="https://habrastorage.org/webt/p7/ex/r8/p7exr8rg5swkkvofqlgmh4stice.jpeg" width="150px"/>

    #### Free rotation/translation - exact
    ```rs
  22. @munrocket munrocket revised this gist Jul 18, 2021. 1 changed file with 8 additions and 7 deletions.
    15 changes: 8 additions & 7 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -438,19 +438,19 @@ fn opIntersectionRound(a: f32, b: f32, r: f32) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/th/2z/xx/th2zxxyqqjohcut6ospfu69bqpw.jpeg" width="450px">

    #### Smooth Union, Smooth Subtraction, Smooth Intersection - bound, bound, bound
    #### Blend Union, Blend Subtraction, Blend Intersection - bound, bound, bound
    ```rs
    fn opUnionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    fn opUnionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0., 1.);
    return mix(d2, d1, h) - k * h * (1. - h);
    }

    fn opSubtractionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    fn opSubtractionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 - 0.5 * (d1 + d2) / k, 0., 1.);
    return mix(d1, -d2, h) + k * h * (1. - h);
    }

    fn opIntersectionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    fn opIntersectionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 - 0.5 * (d2 - d1) / k, 0., 1.);
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    @@ -496,11 +496,12 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {

    #### 90 degree Oz rotation - exact
    ```rs
    fn op90RotateZ(p: vec3<f32>) -> f32 {
    let p0 = vec3<f32>(p.y, -p.x, p.z);
    return sdfPrimitive3d(p0);
    fn op90RotateZ(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(-p.z, p.y, p.x);
    }
    //let d = sdfPrimitive3d(op90RotateZ(p));
    ```
    <img src="https://habrastorage.org/webt/7h/he/pa/7hhepatlqmihfu7qy8xzkcx5udm.jpeg" width="150px"/>

    #### Oz rotation - exact
    ```rs
  23. @munrocket munrocket revised this gist Jul 17, 2021. 1 changed file with 41 additions and 37 deletions.
    78 changes: 41 additions & 37 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -422,8 +422,8 @@ fn opIntersectionChamfer(a: f32, b: f32, r: f32) -> f32 {
    #### Round Union, Round Subtraction, Round Intersection - bound, bound, bound
    ```rs
    fn opUnionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r - a, r - b), vec2<f32>(0.));
    return max(r, min(a, b)) - length(u);
    let u = max(vec2<f32>(r - a, r - b), vec2<f32>(0.));
    return max(r, min(a, b)) - length(u);
    }

    fn opSubtractionRound (a: f32, b: f32, r: f32) -> f32 {
    @@ -432,8 +432,8 @@ fn opSubtractionRound (a: f32, b: f32, r: f32) -> f32 {
    }

    fn opIntersectionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r + a, r + b), vec2<f32>(0.));
    return min(-r, max(a, b)) + length(u);
    let u = max(vec2<f32>(r + a, r + b), vec2<f32>(0.));
    return min(-r, max(a, b)) + length(u);
    }
    ```
    <img src="https://habrastorage.org/webt/th/2z/xx/th2zxxyqqjohcut6ospfu69bqpw.jpeg" width="450px">
    @@ -485,7 +485,7 @@ fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.x);
    let c = cos(k * p.x);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    let m = mat2x2<f32>(vec2<f32>(c, s), vec2<f32>(-s, c));
    return vec3<f32>(m * p.xy, p.z);
    }
    //let d = sdfPrimitive3d(opCheapBend(p, k));
    @@ -504,65 +504,68 @@ fn op90RotateZ(p: vec3<f32>) -> f32 {

    #### Oz rotation - exact
    ```rs
    fn opRotateZ(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    let p0 = vec3<f32>(sincos[1] * p.x + sincos[0] * p.y, -sincos[0] * p.x + sincos[1] * p.y, p.z);
    return sdfPrimitive3d(p0);
    fn opRotateZ(p: vec3<f32>, sincos: vec2<f32>) -> vec3<f32> {
    return vec3<f32>(sincos[1] * p.x + sincos[0] * p.y, -sincos[0] * p.x + sincos[1] * p.y, p.z);
    }
    //let d = sdfPrimitive3d(op90RotateZ(p, sincos));
    ```

    #### Scale - exact
    ```rs
    fn opScale(p: vec3<f32>, s: f32) -> f32 {
    return sdfPrimitive3d(p / s) * s;
    fn opScale(p: vec3<f32>, s: f32) -> vec3<f32> {
    return p / s;
    }
    //let d = sdfPrimitive3d(opScale(p, s)) * s;
    ```

    #### Free rotation/translation - exact
    ```rs
    fn opTransform(p: vec3<f32>, inversedTransform: mat4x4<f32>) -> f32 {
    let p0 = inversedTransform * vec4(p, 1.);
    return sdfPrimitive3d(p0);
    fn opTransform(p: vec3<f32>, transform: mat4x4<f32>) -> vec3<f32> {
    let q = inverse(transform) * vec4<f32>(p, 1.);
    }
    //let d = sdfPrimitive3d(opTransform(p, transform)) * determinant(transform);
    ```

    #### Symmetry - exact
    ```rs
    fn opSymmetryX(p: vec3<f32>) -> f32 {
    let p0 = vec3<f32>(abs(p.x), p.y, p.z);
    return sdfPrimitive3d(p0);
    fn opSymmetryX(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(abs(p.x), p.y, p.z);
    }
    //let d = sdfPrimitive3d(opSymmetryX(p));
    ```

    #### Infinite Repetition - exact
    ```rs
    fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> f32 {
    let p0 = (p + 0.5 * c % c) - 0.5 * c;
    return sdfPrimitive3d(p0);
    fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> vec3<f32> {
    return (p + 0.5 * c % c) - 0.5 * c;
    }
    //let d = sdfPrimitive3d(opInfArray(p, c));
    ```

    #### Finite Repetition - exact
    ```rs
    fn opLimArray(p: vec3<f32>, c: f32, lim: vec3<f32>) -> f32 {
    let p0 = p - c * clamp(round(p / c), -lim, lim);
    return sdfPrimitive3d(p0);
    fn opLimArray(p: vec3<f32>, c: f32, lim: vec3<f32>) -> vec3<f32> {
    return p - c * clamp(round(p / c), -lim, lim);
    }
    //let d = sdfPrimitive3d(opLimArray(p, c));
    ```

    # Primitive alterations

    #### Elongation - exact
    ```rs
    fn opElongateFast(p: vec3<f32>, h: vec3<f32>) -> f32 {
    let p0 = p - clamp(p, -h, h);
    return sdfPrimitive3d(p0);
    fn opElongateFast(p: vec3<f32>, h: vec3<f32>) -> vec3<f32> {
    return p - clamp(p, -h, h);
    }
    //let d = sdfPrimitive3d(opElongateFast(p, h));

    fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> f32 {
    let p0 = abs(p) - h;
    let c = min(max(p0.x, max(p0.y, p0.z)), 0.);
    return c + sdfPrimitive3d(max(p0, vec3<f32>(0.)));
    fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> vec4<f32> {
    let p2 = abs(p) - h;
    let c = min(max(p2.x, max(p2.y, p2.z)), 0.);
    return vec4<f32>(max(p2, vec3<f32>(0.)), c);
    }
    //let p2 = opElongateCorrect(p, h);
    //let d = p2.w + sdfPrimitive3d(p2.xyz);
    ```

    #### Rounding - exact
    @@ -574,26 +577,27 @@ fn opRound(p: vec3<f32>, r: f32) -> f32 {

    #### Onion - exact
    ```rs
    fn opOnion(sdf: f32, thickness: f32) -> f32 {
    return abs(sdf) - thickness;
    fn opOnion(d: f32, thickness: f32) -> f32 {
    return abs(d) - thickness;
    }
    //let d = opOnion(sdfPrimitive3d(p), thickness);
    ```

    #### Extrusion from 2D SDF - exact
    ```rs
    fn opExtrusion(p: vec3<f32>, h: f32) -> f32 {
    let d = sdfPrimitive2d(p.xy);
    let w = vec2<f32>(d, abs(p.z) - h);
    fn opExtrusion(d: f32, z: f32, h: f32) -> f32 {
    let w = vec2<f32>(d, abs(z) - h);
    return min(max(w.x, w.y), 0.) + length(max(w, vec2<f32>(0.)));
    }
    //let d = opExtrusion(sdfPrimitive2d(p.xy), p.z, h));
    ```

    #### Revolution from 2D SDF - exact
    ```rs
    fn opRevolution(p: vec3<f32>, o: f32) -> f32 {
    let q = vec2<f32>(length(p.xz) - o, p.y);
    return sdfPrimitive2d(q);
    fn opRevolution(p: vec3<f32>, o: f32) -> vec2<f32> {
    return vec2<f32>(length(p.xz) - o, p.y);
    }
    //let d = sdfPrimitive2d(opRevolution(p, h));
    ```

    #### Change metric - bound
  24. @munrocket munrocket revised this gist Jul 17, 2021. 1 changed file with 55 additions and 36 deletions.
    91 changes: 55 additions & 36 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -17,7 +17,7 @@ fn sdSphere(p: vec3<f32>, r: f32) -> f32 {
    return length(p) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px">

    #### Ellipsoid - bound (not exact)
    ```rs
    @@ -27,7 +27,7 @@ fn sdEllipsoid(p: vec3<f32>, r: vec3<f32>) -> f32 {
    return k0 * (k0 - 1.) / k1;
    }
    ```
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px">

    #### Box - exact
    ```rs
    @@ -36,7 +36,7 @@ fn sdBox(p: vec3<f32>, b: vec3<f32>) -> f32 {
    return length(max(q, vec3<f32>(0.))) + min(max(q.x, max(q.y, q.z)), 0.);
    }
    ```
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px">

    #### Round Box - exact
    ```rs
    @@ -45,7 +45,7 @@ fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return length(max(q, vec3<f32>(0.))) + min(max(q.x,max(q.y, q.z)), 0.) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px">

    #### Box Frame - exact
    ```rs
    @@ -58,7 +58,7 @@ fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    length(max(vec3<f32>(w.x, w.y, q.z), vec3<f32>(0.))) + min(max(w.x, max(w.y, q.z)), 0.));
    }
    ```
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px">

    #### Torus - exact
    ```rs
    @@ -67,7 +67,7 @@ fn sdTorus(p: vec3<f32>, R: f32, r: f32) -> f32 {
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px">

    #### Capped Torus - exact
    ```rs
    @@ -77,7 +77,7 @@ fn sdCappedTorus(p: vec3<f32>, R: f32, r: f32, sincos: vec2<f32>) -> f32 {
    return sqrt(dot(q, q) + R * R - 2. * R * k) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px">

    #### Link - exact
    ```rs
    @@ -86,7 +86,7 @@ fn sdLink(p: vec3<f32>, R: f32, r: f32, le: f32) -> f32 {
    return length(vec2<f32>(length(q.xy) - R, q.z)) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px">

    #### Capsule / Line - exact
    ```rs
    @@ -97,7 +97,7 @@ fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return length(pa - ba * h) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px">

    #### Vertical Capsule / Line - exact
    ```rs
    @@ -106,7 +106,7 @@ fn sdVerticalCapsule(p: vec3<f32>, h: f32, r: f32) -> f32 {
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px">

    #### Cylinder - exact
    ```rs
    @@ -124,7 +124,7 @@ fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return sign(d2) * sqrt(abs(d2)) / baba;
    }
    ```
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px">

    #### Vertical Cylinder - exact
    ```rs
    @@ -133,7 +133,7 @@ fn sdVerticalCylinder(p: vec3<f32>, h: f32, r: f32) -> f32 {
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px">

    #### Rounded Cylinder - exact
    ```rs
    @@ -142,15 +142,15 @@ fn sdRoundedCylinder(p: vec3<f32>, h: f32, r: f32, re: f32) -> f32 {
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.))) - re;
    }
    ```
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px">

    #### Infinite Cylinder - exact
    ```rs
    fn sdInfiniteCylinder(p: vec3<f32>, c: vec3<f32>) -> f32 {
    return length(p.xz - c.xy) - c.z;
    }
    ```
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px">

    #### Cone - exact
    ```rs
    @@ -167,15 +167,15 @@ fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return sqrt(d) * sign(s);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px">

    #### Cone - bound (not exact)
    ```rs
    fn sdConeBound(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return max(dot(sincos.yx, vec2<f32>(length(p.xz), p.y)), -h - p.y);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px">

    #### Infinite Cone - exact
    ```rs
    @@ -185,7 +185,7 @@ fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    return d * select(1., -1., q.x * sincos.y - q.y * sincos.x > 0.0);
    }
    ```
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px">

    #### Capped Vertical Cone - exact
    ```rs
    @@ -199,7 +199,7 @@ fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return s * sqrt(min(dot(ca, ca), dot(cb, cb)));
    }
    ```
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px">

    #### Capped Cone - exact
    ```rs
    @@ -219,7 +219,7 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f
    return s * sqrt(min(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba));
    }
    ```
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px">

    #### Round Vertical cone - exact
    ```rs
    @@ -233,7 +233,7 @@ fn sdRoundVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return dot(q, vec2<f32>(a, b)) - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px">

    #### Round cone - exact
    ```rs
    @@ -258,7 +258,7 @@ fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f3
    return (sqrt(x2 * a2 * il2) + y * rr) * il2 - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px">

    #### Solid Angle - exact
    ```rs
    @@ -269,7 +269,7 @@ fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    return max(l, m * sign(sincos.y * q.x - sincos.x * q.y));
    }
    ```
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px">

    #### Plane - exact
    ```rs
    @@ -278,7 +278,7 @@ fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
    return dot(p, n) + h;
    }
    ```
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px">

    #### Octahedron - exact
    ```rs
    @@ -293,7 +293,7 @@ fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    return length(vec3<f32>(q.x, q.y - s + k, q.z - k));
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px">

    #### Octahedron - bound (not exact)
    ```rs
    @@ -302,7 +302,7 @@ fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {
    return (q.x + q.y + q.z - s) * 0.57735027;
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px">

    #### Pyramid - exact
    ```rs
    @@ -323,7 +323,7 @@ fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    return sqrt((d2 + q.z * q.z) / m2) * sign(max(q.z, -p.y));
    }
    ```
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px">

    #### Hexagonal Prism - exact
    ```rs
    @@ -336,7 +336,7 @@ fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    return min(max(d1, d2), 0.) + length(max(vec2<f32>(d1, d2), vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px">

    #### Triangular Prism - bound
    ```rs
    @@ -345,7 +345,7 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    return max(q.z - h.y, max(q.x * 0.866025 + p.y * 0.5, -p.y) - h.x * 0.5);
    }
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px">

    #### Triangle - exact
    ```rs
    @@ -366,7 +366,7 @@ fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    return sqrt(select(k0, k1, t < 2.));
    }
    ```
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px">

    #### Quad - exact
    ```rs
    @@ -389,7 +389,7 @@ fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>)
    return sqrt(select(k0, k1, t < 3.));
    }
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px">

    # Boolean operations with primitives

    @@ -401,7 +401,7 @@ fn opSubtraction(d1: f32, d2: f32) -> f32 { return max(d1, -d2); }

    fn opIntersection(d1: f32, d2: f32) -> f32 { return max(d1, d2); }
    ```
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px">

    #### Chamfer Union, Chamfer Subtraction, Chamfer Intersection - bound, bound, bound
    ```rs
    @@ -417,7 +417,26 @@ fn opIntersectionChamfer(a: f32, b: f32, r: f32) -> f32 {
    return max(max(a, b), (a + r + b) * sqrt(0.5));
    }
    ```
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/tg/vq/jr/tgvqjr32gtadua4rib-fvfxz4ta.jpeg" width="450px">

    #### Round Union, Round Subtraction, Round Intersection - bound, bound, bound
    ```rs
    fn opUnionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r - a, r - b), vec2<f32>(0.));
    return max(r, min(a, b)) - length(u);
    }

    fn opSubtractionRound (a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r + a, r - b), vec2<f32>(0.));
    return min(-r, max(a, -b)) + length(u);
    }

    fn opIntersectionRound(a: f32, b: f32, r: f32) -> f32 {
    let u = max(vec2<f32>(r + a, r + b), vec2<f32>(0.));
    return min(-r, max(a, b)) + length(u);
    }
    ```
    <img src="https://habrastorage.org/webt/th/2z/xx/th2zxxyqqjohcut6ospfu69bqpw.jpeg" width="450px">

    #### Smooth Union, Smooth Subtraction, Smooth Intersection - bound, bound, bound
    ```rs
    @@ -436,7 +455,7 @@ fn opIntersectionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    ```
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px">

    # Displacement

    @@ -447,7 +466,7 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {
    }
    //let d = opDisplace(sdfPrimitive3d(p), displacement3d(p));
    ```
    <img src="https://habrastorage.org/webt/7g/zc/vh/7gzcvhiv_dprnk4ohfjltszz510.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/7g/zc/vh/7gzcvhiv_dprnk4ohfjltszz510.jpeg" width="150px">

    #### Twist - bound
    ```rs
    @@ -459,7 +478,7 @@ fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opTwist(p, k));
    ```
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="150px">

    #### Bend - bound
    ```rs
    @@ -471,7 +490,7 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opCheapBend(p, k));
    ```
    <img src="https://habrastorage.org/webt/q4/ej/aq/q4ejaq0uqgw91xr1cbeptz0gmmi.jpeg" width="150px" height="100px">
    <img src="https://habrastorage.org/webt/q4/ej/aq/q4ejaq0uqgw91xr1cbeptz0gmmi.jpeg" width="150px">

    # Positioning

  25. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -453,7 +453,7 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {
    ```rs
    fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.y);
    let c = cos(k * p.x);
    let c = cos(k * p.y);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    return vec3<f32>(m * p.xz, p.y);
    }
  26. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -453,7 +453,7 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {
    ```rs
    fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.y);
    let c = sqrt(1. - s * s);
    let c = cos(k * p.x);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    return vec3<f32>(m * p.xz, p.y);
    }
    @@ -465,7 +465,7 @@ fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    ```rs
    fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.x);
    let c = sqrt(1. - s * s);
    let c = cos(k * p.x);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    return vec3<f32>(m * p.xy, p.z);
    }
  27. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -447,7 +447,7 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {
    }
    //let d = opDisplace(sdfPrimitive3d(p), displacement3d(p));
    ```
    <img src="https://habrastorage.org/webt/7g/zc/vh/7gzcvhiv_dprnk4ohfjltszz510.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/7g/zc/vh/7gzcvhiv_dprnk4ohfjltszz510.jpeg" width="150px" height="100px">

    #### Twist - bound
    ```rs
    @@ -459,7 +459,7 @@ fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opTwist(p, k));
    ```
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="150px" height="100px">

    #### Bend - bound
    ```rs
    @@ -471,7 +471,7 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    }
    //let d = sdfPrimitive3d(opCheapBend(p, k));
    ```
    <img src="https://habrastorage.org/webt/q4/ej/aq/q4ejaq0uqgw91xr1cbeptz0gmmi.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/q4/ej/aq/q4ejaq0uqgw91xr1cbeptz0gmmi.jpeg" width="150px" height="100px">

    # Positioning

  28. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 15 additions and 11 deletions.
    26 changes: 15 additions & 11 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -436,38 +436,42 @@ fn opIntersectionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    ```
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px" height="100px">

    # Displacement

    #### Displacement - bound (not exact)
    ```rs
    fn opDisplace(sdf: f32, displacement: f32) -> f32 {
    return sdf + displacement;
    fn opDisplace(d1: f32, d2: f32) -> f32 {
    return d1 + d2;
    }
    //let d = opDisplace(sdfPrimitive3d(p), displacement3d(p));
    ```
    <img src="https://habrastorage.org/webt/7g/zc/vh/7gzcvhiv_dprnk4ohfjltszz510.jpeg" width="450px" height="100px">

    #### Twist - bound
    ```rs
    fn opTwist(p: vec3<f32>, k: f32) -> f32 {
    let c = cos(k * p.y);
    fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.y);
    let c = sqrt(1. - s * s);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    let p0 = vec3<f32>(m * p.xz, p.y);
    return sdfPrimitive3d(p0);
    return vec3<f32>(m * p.xz, p.y);
    }
    //let d = sdfPrimitive3d(opTwist(p, k));
    ```
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="450px" height="100px">

    #### Bend - bound
    ```rs
    fn opCheapBend(p: vec3<f32>, k: f32) -> f32 {
    let c = cos(k * p.x);
    fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    let s = sin(k * p.x);
    let c = sqrt(1. - s * s);
    let m = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
    let p0 = vec3<f32>(m * p.xy, p.z);
    return sdfPrimitive3d(p0);
    return vec3<f32>(m * p.xy, p.z);
    }
    //let d = sdfPrimitive3d(opCheapBend(p, k));
    ```
    <img src="https://habrastorage.org/webt/q4/ej/aq/q4ejaq0uqgw91xr1cbeptz0gmmi.jpeg" width="450px" height="100px">

    # Positioning

  29. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 37 additions and 37 deletions.
    74 changes: 37 additions & 37 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # 3D SDF Primitives in WGSL

    How to use this gist:
    #### How to use this gist:
    1. Build a sphere tracer with WebGPU ([paper](https://www.researchgate.net/publication/2792108_Sphere_Tracing_A_Geometric_Method_for_the_Antialiased_Ray_Tracing_of_Implicit_Surfaces), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
    2. Create model with sdf functions from here
    3. Add light and shadows
    @@ -12,43 +12,42 @@ This code tested in Chrome and Firefox, should work on PC too. Press star and su
    # Primitives

    #### Sphere - exact
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px" height="100px">
    ```rs
    fn sdSphere(p: vec3<f32>, r: f32) -> f32 {
    return length(p) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px" height="100px">

    #### Ellipsoid - bound (not exact)
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px" height="100px">
    ```rs
    fn sdEllipsoid(p: vec3<f32>, r: vec3<f32>) -> f32 {
    let k0 = length(p / r);
    let k1 = length(p / (r * r));
    return k0 * (k0 - 1.) / k1;
    }
    ```
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px" height="100px">

    #### Box - exact
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px" height="100px">
    ```rs
    fn sdBox(p: vec3<f32>, b: vec3<f32>) -> f32 {
    let q = abs(p) - b;
    return length(max(q, vec3<f32>(0.))) + min(max(q.x, max(q.y, q.z)), 0.);
    }
    ```
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px" height="100px">

    #### Round Box - exact
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let q = abs(p) - b;
    return length(max(q, vec3<f32>(0.))) + min(max(q.x,max(q.y, q.z)), 0.) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px" height="100px">

    #### Box Frame - exact
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px" height="100px">
    ```rs
    fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    let q = abs(p) - b;
    @@ -59,37 +58,37 @@ fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    length(max(vec3<f32>(w.x, w.y, q.z), vec3<f32>(0.))) + min(max(w.x, max(w.y, q.z)), 0.));
    }
    ```
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px" height="100px">

    #### Torus - exact
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px" height="100px">
    ```rs
    fn sdTorus(p: vec3<f32>, R: f32, r: f32) -> f32 {
    let q = vec2<f32>(length(p.xz) - R, p.y);
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px" height="100px">

    #### Capped Torus - exact
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedTorus(p: vec3<f32>, R: f32, r: f32, sincos: vec2<f32>) -> f32 {
    let q = vec3<f32>(abs(p.x), p.y, p.z);
    let k = select(dot(q.xy, sincos), length(q.xy), sincos.y * q.x > sincos.x * q.y);
    return sqrt(dot(q, q) + R * R - 2. * R * k) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px" height="100px">

    #### Link - exact
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px" height="100px">
    ```rs
    fn sdLink(p: vec3<f32>, R: f32, r: f32, le: f32) -> f32 {
    let q = vec3<f32>(p.x, max(abs(p.y) - le, 0.), p.z);
    return length(vec2<f32>(length(q.xy) - R, q.z)) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px" height="100px">

    #### Capsule / Line - exact
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px" height="100px">
    ```rs
    fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let pa = p - a;
    @@ -98,18 +97,18 @@ fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return length(pa - ba * h) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px" height="100px">

    #### Vertical Capsule / Line - exact
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px" height="100px">
    ```rs
    fn sdVerticalCapsule(p: vec3<f32>, h: f32, r: f32) -> f32 {
    let q = vec3<f32>(p.x, p.y - clamp(p.y, 0., h), p.z);
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px" height="100px">

    #### Cylinder - exact
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px" height="100px">
    ```rs
    fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let ba = b - a;
    @@ -125,35 +124,35 @@ fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return sign(d2) * sqrt(abs(d2)) / baba;
    }
    ```
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px" height="100px">

    #### Vertical Cylinder - exact
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px" height="100px">
    ```rs
    fn sdVerticalCylinder(p: vec3<f32>, h: f32, r: f32) -> f32 {
    let d = abs(vec2<f32>(length(p.xz), p.y)) - vec2<f32>(r, h);
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px" height="100px">

    #### Rounded Cylinder - exact
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundedCylinder(p: vec3<f32>, h: f32, r: f32, re: f32) -> f32 {
    let d = vec2<f32>(length(p.xz) - 2. * r + re, abs(p.y) - h);
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.))) - re;
    }
    ```
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px" height="100px">

    #### Infinite Cylinder - exact
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px" height="100px">
    ```rs
    fn sdInfiniteCylinder(p: vec3<f32>, c: vec3<f32>) -> f32 {
    return length(p.xz - c.xy) - c.z;
    }
    ```
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px" height="100px">

    #### Cone - exact
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    ```rs
    fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    // Alternatively pass q instead of (sin(alpha), cos(alpha))
    @@ -168,27 +167,27 @@ fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return sqrt(d) * sign(s);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">

    #### Cone - bound (not exact)
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    ```rs
    fn sdConeBound(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return max(dot(sincos.yx, vec2<f32>(length(p.xz), p.y)), -h - p.y);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">

    #### Infinite Cone - exact
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px" height="100px">
    ```rs
    fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    let q = vec2<f32>(length(p.xz), -p.y);
    let d = length(q - sincos * max(dot(q, sincos), 0.));
    return d * select(1., -1., q.x * sincos.y - q.y * sincos.x > 0.0);
    }
    ```
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px" height="100px">

    #### Capped Vertical Cone - exact
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -200,9 +199,9 @@ fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return s * sqrt(min(dot(ca, ca), dot(cb, cb)));
    }
    ```
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px" height="100px">

    #### Capped Cone - exact
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f32 {
    let rba = rb - ra;
    @@ -220,9 +219,9 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f
    return s * sqrt(min(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba));
    }
    ```
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px" height="100px">

    #### Round Vertical cone - exact
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -234,9 +233,9 @@ fn sdRoundVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return dot(q, vec2<f32>(a, b)) - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px" height="100px">

    #### Round cone - exact
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f32 {
    let ba = b - a;
    @@ -259,9 +258,9 @@ fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f3
    return (sqrt(x2 * a2 * il2) + y * rr) * il2 - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px" height="100px">

    #### Solid Angle - exact
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px" height="100px">
    ```rs
    fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -270,18 +269,18 @@ fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    return max(l, m * sign(sincos.y * q.x - sincos.x * q.y));
    }
    ```
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px" height="100px">

    #### Plane - exact
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px" height="100px">
    ```rs
    fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
    // n must be normalized
    return dot(p, n) + h;
    }
    ```
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px" height="100px">

    #### Octahedron - exact
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    ```rs
    fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    var q: vec3<f32> = abs(p);
    @@ -294,18 +293,18 @@ fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    return length(vec3<f32>(q.x, q.y - s + k, q.z - k));
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">

    #### Octahedron - bound (not exact)
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    ```rs
    fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {
    let q = abs(p);
    return (q.x + q.y + q.z - s) * 0.57735027;
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">

    #### Pyramid - exact
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px" height="100px">
    ```rs
    fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    let m2 = h * h + 0.25;
    @@ -324,9 +323,9 @@ fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    return sqrt((d2 + q.z * q.z) / m2) * sign(max(q.z, -p.y));
    }
    ```
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px" height="100px">

    #### Hexagonal Prism - exact
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px" height="100px">
    ```rs
    fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    let k = vec3<f32>(-0.8660254, 0.5, 0.57735);
    @@ -337,18 +336,18 @@ fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    return min(max(d1, d2), 0.) + length(max(vec2<f32>(d1, d2), vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px" height="100px">

    #### Triangular Prism - bound
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px" height="100px">
    ```rs
    fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    let q = abs(p);
    return max(q.z - h.y, max(q.x * 0.866025 + p.y * 0.5, -p.y) - h.x * 0.5);
    }
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px" height="100px">

    #### Triangle - exact
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px" height="100px">
    ```rs
    fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    @@ -367,9 +366,9 @@ fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    return sqrt(select(k0, k1, t < 2.));
    }
    ```
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px" height="100px">

    #### Quad - exact
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px" height="100px">
    ```rs
    fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    @@ -390,37 +389,37 @@ fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>)
    return sqrt(select(k0, k1, t < 3.));
    }
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px" height="100px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px" height="100px">
    ```rs
    fn opUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }

    fn opSubtraction(d1: f32, d2: f32) -> f32 { return max(d1, -d2); }

    fn opIntersection(d1: f32, d2: f32) -> f32 { return max(d1, d2); }
    ```
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px" height="100px">

    #### Chamfer Union, Chamfer Subtraction, Chamfer Intersection - bound, bound, bound
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">
    ```rs
    fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * sqrt(0.5));
    return min(min(d1, d2), (d1 - r + d2) * sqrt(0.5));
    }

    fn opSubtractionChamfer(a: f32, b: f32, r: f32) -> f32{
    return max(max(a, -b), (a + r - b) * sqrt(0.5));
    return max(max(a, -b), (a + r - b) * sqrt(0.5));
    }

    fn opIntersectionChamfer(a: f32, b: f32, r: f32) -> f32 {
    return max(max(a, b), (a + r + b) * sqrt(0.5));
    return max(max(a, b), (a + r + b) * sqrt(0.5));
    }
    ```
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">

    #### Smooth Union, Smooth Subtraction, Smooth Intersection - bound, bound, bound
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px" height="100px">
    ```rs
    fn opUnionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0., 1.);
    @@ -437,6 +436,7 @@ fn opIntersectionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    ```
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">

    # Displacement

  30. @munrocket munrocket revised this gist Jul 16, 2021. 1 changed file with 39 additions and 43 deletions.
    82 changes: 39 additions & 43 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -1,54 +1,54 @@
    # 3D SDF Primitives in WGSL

    #### How to use this gist:

    How to use this gist:
    1. Build a sphere tracer with WebGPU ([paper](https://www.researchgate.net/publication/2792108_Sphere_Tracing_A_Geometric_Method_for_the_Antialiased_Ray_Tracing_of_Implicit_Surfaces), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
    2. Create model with sdf functions from here
    3. Add light and shadows
    4. ???
    5. PROFIT

    > This code tested in Chrome and Firefox, should work on PC too. Press star and subscribe.
    This code tested in Chrome and Firefox, should work on PC too. Press star and subscribe.

    # Primitives

    #### Sphere - exact
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px" height="100px">
    ```rs
    fn sdSphere(p: vec3<f32>, r: f32) -> f32 {
    return length(p) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/9s/1j/gw/9s1jgwsvfhr9-q0v1n1xpgozm3i.jpeg" width="150px" height="100px">

    #### Ellipsoid - bound (not exact)
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px" height="100px">
    ```rs
    fn sdEllipsoid(p: vec3<f32>, r: vec3<f32>) -> f32 {
    let k0 = length(p / r);
    let k1 = length(p / (r * r));
    return k0 * (k0 - 1.) / k1;
    }
    ```
    <img src="https://habrastorage.org/webt/zz/fd/fw/zzfdfwtf4mmb0db7mzpwr0kyoqa.jpeg" width="150px" height="100px">

    #### Box - exact
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px" height="100px">
    ```rs
    fn sdBox(p: vec3<f32>, b: vec3<f32>) -> f32 {
    let q = abs(p) - b;
    return length(max(q, vec3<f32>(0.))) + min(max(q.x, max(q.y, q.z)), 0.);
    }
    ```
    <img src="https://habrastorage.org/webt/j0/jp/rp/j0jprpokpxonzzpiz9zdm1qh2os.jpeg" width="150px" height="100px">

    #### Round Box - exact
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let q = abs(p) - b;
    return length(max(q, vec3<f32>(0.))) + min(max(q.x,max(q.y, q.z)), 0.) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/vf/g0/ze/vfg0zewp6rc61gnwnextb8v3lo4.jpeg" width="150px" height="100px">

    #### Box Frame - exact
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px" height="100px">
    ```rs
    fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    let q = abs(p) - b;
    @@ -59,37 +59,37 @@ fn sdBoxFrame(p: vec3<f32>, b: vec3<f32>, e: f32) -> f32 {
    length(max(vec3<f32>(w.x, w.y, q.z), vec3<f32>(0.))) + min(max(w.x, max(w.y, q.z)), 0.));
    }
    ```
    <img src="https://habrastorage.org/webt/tx/7v/gb/tx7vgburvrj0rlrgsgxea1c0dni.jpeg" width="150px" height="100px">

    #### Torus - exact
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px" height="100px">
    ```rs
    fn sdTorus(p: vec3<f32>, R: f32, r: f32) -> f32 {
    let q = vec2<f32>(length(p.xz) - R, p.y);
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/7j/lz/fi/7jlzfitp9knoablnx38najyz8hu.jpeg" width="150px" height="100px">

    #### Capped Torus - exact
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedTorus(p: vec3<f32>, R: f32, r: f32, sincos: vec2<f32>) -> f32 {
    let q = vec3<f32>(abs(p.x), p.y, p.z);
    let k = select(dot(q.xy, sincos), length(q.xy), sincos.y * q.x > sincos.x * q.y);
    return sqrt(dot(q, q) + R * R - 2. * R * k) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/lr/gf/mw/lrgfmwb0yfwaipf1rj3_vzu-tzm.jpeg" width="150px" height="100px">

    #### Link - exact
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px" height="100px">
    ```rs
    fn sdLink(p: vec3<f32>, R: f32, r: f32, le: f32) -> f32 {
    let q = vec3<f32>(p.x, max(abs(p.y) - le, 0.), p.z);
    return length(vec2<f32>(length(q.xy) - R, q.z)) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/fk/du/dh/fkdudhqfxcgl3m7fylehvsetnqa.jpeg" width="150px" height="100px">

    #### Capsule / Line - exact
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px" height="100px">
    ```rs
    fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let pa = p - a;
    @@ -98,18 +98,18 @@ fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return length(pa - ba * h) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/o6/ei/u3/o6eiu3wxukv8jw-owmgegdy27u4.jpeg" width="150px" height="100px">

    #### Vertical Capsule / Line - exact
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px" height="100px">
    ```rs
    fn sdVerticalCapsule(p: vec3<f32>, h: f32, r: f32) -> f32 {
    let q = vec3<f32>(p.x, p.y - clamp(p.y, 0., h), p.z);
    return length(q) - r;
    }
    ```
    <img src="https://habrastorage.org/webt/0l/nd/ot/0lndot80hvqtbnhh_6-ncloz7io.jpeg" width="150px" height="100px">

    #### Cylinder - exact
    #### Cylinder - exact
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px" height="100px">
    ```rs
    fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    let ba = b - a;
    @@ -125,35 +125,35 @@ fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    return sign(d2) * sqrt(abs(d2)) / baba;
    }
    ```
    <img src="https://habrastorage.org/webt/33/v-/xz/33v-xz4gqpq_hy2v01mreala19u.jpeg" width="150px" height="100px">

    #### Vertical Cylinder - exact
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px" height="100px">
    ```rs
    fn sdVerticalCylinder(p: vec3<f32>, h: f32, r: f32) -> f32 {
    let d = abs(vec2<f32>(length(p.xz), p.y)) - vec2<f32>(r, h);
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/wr/lx/lq/wrlxlqcrexycg7fkfiygip_18u8.jpeg" width="150px" height="100px">

    #### Rounded Cylinder - exact
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundedCylinder(p: vec3<f32>, h: f32, r: f32, re: f32) -> f32 {
    let d = vec2<f32>(length(p.xz) - 2. * r + re, abs(p.y) - h);
    return min(max(d.x, d.y), 0.) + length(max(d, vec2<f32>(0.))) - re;
    }
    ```
    <img src="https://habrastorage.org/webt/d9/qs/3w/d9qs3wpn4bqozwi0vsgqw8xqps8.jpeg" width="150px" height="100px">

    #### Infinite Cylinder - exact
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px" height="100px">
    ```rs
    fn sdInfiniteCylinder(p: vec3<f32>, c: vec3<f32>) -> f32 {
    return length(p.xz - c.xy) - c.z;
    }
    ```
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px" height="100px">

    #### Cone - exact
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    ```rs
    fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    // Alternatively pass q instead of (sin(alpha), cos(alpha))
    @@ -168,27 +168,27 @@ fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return sqrt(d) * sign(s);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">

    #### Cone - bound (not exact)
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">
    ```rs
    fn sdConeBound(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    return max(dot(sincos.yx, vec2<f32>(length(p.xz), p.y)), -h - p.y);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px" height="100px">

    #### Infinite Cone - exact
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px" height="100px">
    ```rs
    fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    let q = vec2<f32>(length(p.xz), -p.y);
    let d = length(q - sincos * max(dot(q, sincos), 0.));
    return d * select(1., -1., q.x * sincos.y - q.y * sincos.x > 0.0);
    }
    ```
    <img src="https://habrastorage.org/webt/39/j5/fs/39j5fsjq-6onu2lxbwtakun5g1k.jpeg" width="150px" height="100px">

    #### Capped Vertical Cone - exact
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -200,9 +200,9 @@ fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return s * sqrt(min(dot(ca, ca), dot(cb, cb)));
    }
    ```
    <img src="https://habrastorage.org/webt/p4/br/qq/p4brqq1bibmhil4njb9v8bjwb8s.jpeg" width="150px" height="100px">

    #### Capped Cone - exact
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px" height="100px">
    ```rs
    fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f32 {
    let rba = rb - ra;
    @@ -220,9 +220,9 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f
    return s * sqrt(min(cax * cax + cay * cay * baba, cbx * cbx + cby * cby * baba));
    }
    ```
    <img src="https://habrastorage.org/webt/ch/7i/gv/ch7igvrlcmjtn38qciwdzpwckfg.jpeg" width="150px" height="100px">

    #### Round Vertical cone - exact
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -234,9 +234,9 @@ fn sdRoundVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {
    return dot(q, vec2<f32>(a, b)) - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/rv/ww/-1/rvww-1s4txpfkheptynmb9m2jyg.jpeg" width="150px" height="100px">

    #### Round cone - exact
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px" height="100px">
    ```rs
    fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f32 {
    let ba = b - a;
    @@ -259,9 +259,9 @@ fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f3
    return (sqrt(x2 * a2 * il2) + y * rr) * il2 - r1;
    }
    ```
    <img src="https://habrastorage.org/webt/61/ft/aa/61ftaa1ral1hbj_eijczixm0tnq.jpeg" width="150px" height="100px">

    #### Solid Angle - exact
    #### Solid Angle - exact
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px" height="100px">
    ```rs
    fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    @@ -270,18 +270,18 @@ fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    return max(l, m * sign(sincos.y * q.x - sincos.x * q.y));
    }
    ```
    <img src="https://habrastorage.org/webt/7z/ee/yu/7zeeyuuhnwcrcpmht-h8nxi0em4.jpeg" width="150px" height="100px">

    #### Plane - exact
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px" height="100px">
    ```rs
    fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
    // n must be normalized
    return dot(p, n) + h;
    }
    ```
    <img src="https://habrastorage.org/webt/sz/cn/8x/szcn8xvstcyyb9irdpehjhlpqpk.jpeg" width="150px" height="100px">

    #### Octahedron - exact
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    ```rs
    fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    var q: vec3<f32> = abs(p);
    @@ -294,18 +294,18 @@ fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    return length(vec3<f32>(q.x, q.y - s + k, q.z - k));
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">

    #### Octahedron - bound (not exact)
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">
    ```rs
    fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {
    let q = abs(p);
    return (q.x + q.y + q.z - s) * 0.57735027;
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px" height="100px">

    #### Pyramid - exact
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px" height="100px">
    ```rs
    fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    let m2 = h * h + 0.25;
    @@ -324,9 +324,9 @@ fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    return sqrt((d2 + q.z * q.z) / m2) * sign(max(q.z, -p.y));
    }
    ```
    <img src="https://habrastorage.org/webt/g2/xf/gc/g2xfgc02jc-ty5mlqgyncutoyss.jpeg" width="150px" height="100px">

    #### Hexagonal Prism - exact
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px" height="100px">
    ```rs
    fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    let k = vec3<f32>(-0.8660254, 0.5, 0.57735);
    @@ -337,18 +337,18 @@ fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    return min(max(d1, d2), 0.) + length(max(vec2<f32>(d1, d2), vec2<f32>(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px" height="100px">

    #### Triangular Prism - bound
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px" height="100px">
    ```rs
    fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    let q = abs(p);
    return max(q.z - h.y, max(q.x * 0.866025 + p.y * 0.5, -p.y) - h.x * 0.5);
    }
    ```
    <img src="https://habrastorage.org/webt/zc/2k/2s/zc2k2sm4cudwfsghvk7ibkdztcc.jpeg" width="150px" height="100px">

    #### Triangle - exact
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px" height="100px">
    ```rs
    fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    @@ -367,9 +367,9 @@ fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    return sqrt(select(k0, k1, t < 2.));
    }
    ```
    <img src="https://habrastorage.org/webt/jk/cc/eo/jkcceovnen8mfbwdzyu9gpxcxhi.jpeg" width="150px" height="100px">

    #### Quad - exact
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px" height="100px">
    ```rs
    fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>) -> f32 {
    let ba = b - a; let pa = p - a;
    @@ -390,21 +390,21 @@ fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>)
    return sqrt(select(k0, k1, t < 3.));
    }
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px" height="100px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px" height="100px">
    ```rs
    fn opUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }

    fn opSubtraction(d1: f32, d2: f32) -> f32 { return max(d1, -d2); }

    fn opIntersection(d1: f32, d2: f32) -> f32 { return max(d1, d2); }
    ```
    <img src="https://habrastorage.org/webt/l6/md/vd/l6mdvd5dynh6ewrw3gpmkhsetow.jpeg" width="450px" height="100px">

    #### Chamfer Union, Chamfer Subtraction, Chamfer Intersection - bound, bound, bound
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">
    ```rs
    fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * sqrt(0.5));
    @@ -418,10 +418,9 @@ fn opIntersectionChamfer(a: f32, b: f32, r: f32) -> f32 {
    return max(max(a, b), (a + r + b) * sqrt(0.5));
    }
    ```
    <img src="https://habrastorage.org/webt/hr/oc/te/hroctexybegahwmxcvxgtyk9kcy.jpeg" width="450px" height="100px">

    #### Smooth Union, Smooth Subtraction, Smooth Intersection - bound, bound, bound

    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px" height="100px">
    ```rs
    fn opUnionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    let h = clamp(0.5 + 0.5 * (d2 - d1) / k, 0., 1.);
    @@ -438,16 +437,13 @@ fn opIntersectionSmooth(d1: f32, d2: f32, k: f32) -> f32 {
    return mix(d2, d1, h) + k * h * (1. - h);
    }
    ```
    <img src="https://habrastorage.org/webt/bo/eg/rx/boegrx957wt1t70mfjshhaa11cg.jpeg" width="450px" height="100px">

    # Displacement

    #### Displacement - bound (not exact)
    ```rs
    fn opDisplace(p: vec3<f32>) -> f32 {
    let d1 = sdfPrimitive3d(p);
    let d2 = displacement3d(p);
    return d1 + d2;
    fn opDisplace(sdf: f32, displacement: f32) -> f32 {
    return sdf + displacement;
    }
    ```