Skip to content

Instantly share code, notes, and snippets.

@munrocket
Last active September 6, 2025 09:47
Show Gist options
  • Save munrocket/f247155fc22ecb8edf974d905c677de1 to your computer and use it in GitHub Desktop.
Save munrocket/f247155fc22ecb8edf974d905c677de1 to your computer and use it in GitHub Desktop.

Revisions

  1. munrocket revised this gist Sep 24, 2023. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -490,11 +490,11 @@ fn sdBunny(p: vec3f) -> f32 {

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
    ```rs
    fn opSmoothUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }
    fn opUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }

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

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

    @@ -516,17 +516,17 @@ fn opChamferIntersect(d1: f32, d2: f32, r: f32) -> f32 {

    #### Blend Union, Blend Subtraction, Blend Intersection - bound, bound, bound
    ```rs
    fn opUnion(d1: f32, d2: f32, k: f32) -> f32 {
    fn opSmoothUnion(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 opSubtract(d1: f32, d2: f32, k: f32) -> f32 {
    fn opSmoothSubtract(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 opIntersect(d1: f32, d2: f32, k: f32) -> f32 {
    fn opSmoothIntersect(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);
    }
  2. munrocket revised this gist Sep 24, 2023. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -490,25 +490,25 @@ fn sdBunny(p: vec3f) -> f32 {

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
    ```rs
    fn opUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }
    fn opSmoothUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }

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

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

    #### Chamfer Union, Chamfer Subtraction, Chamfer Intersection - bound, bound, bound
    ```rs
    fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    fn opChamferUnion(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * 0.5);
    }

    fn opSubtractChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    fn opChamferSubtract(d1: f32, d2: f32, r: f32) -> f32 {
    return max(max(d1, -d2), (d1 + r - d2) * 0.5);
    }

    fn opIntersectChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    fn opChamferIntersect(d1: f32, d2: f32, r: f32) -> f32 {
    return max(max(d1, d2), (d1 + r + d2) * 0.5);
    }
    ```
  3. munrocket revised this gist Sep 24, 2023. 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
    @@ -492,9 +492,9 @@ fn sdBunny(p: vec3f) -> f32 {
    ```rs
    fn opUnion(d1: f32, d2: f32) -> f32 { return min(d1, d2); }

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

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

    @@ -504,29 +504,29 @@ fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * 0.5);
    }

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

    fn opIntersectionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    fn opIntersectChamfer(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">

    #### Blend Union, Blend Subtraction, Blend Intersection - bound, bound, bound
    ```rs
    fn opUnionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    fn opUnion(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 opSubtractionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    fn opSubtract(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 opIntersectionBlend(d1: f32, d2: f32, k: f32) -> f32 {
    fn opIntersect(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);
    }
  4. munrocket revised this gist Aug 24, 2023. 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
    @@ -753,4 +753,4 @@ fn length8(p: vec3f) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/uw/dm/oz/uwdmozwn25o_dpcdlsrdb-ppevm.jpeg" width="150px"/>

    MIT License. © 2020 Inigo Quilez, Johann Korndörfer, Martijn Steinrucken, Munrocket
    MIT License. © 2020 Inigo Quilez, Johann Korndörfer, Martijn Steinrucken, Blackle Mori, Munrocket
  5. munrocket revised this gist Aug 22, 2023. 1 changed file with 55 additions and 0 deletions.
    55 changes: 55 additions & 0 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -431,6 +431,61 @@ fn udQuad(p: vec3f, a: vec3f, b: vec3f, c: vec3f, d: vec3f) -> f32 {
    ```
    <img src="https://habrastorage.org/webt/fv/nu/yc/fvnuycg5uvk6bvjthgo8en0_7su.jpeg" width="150px">

    #### Bunny - bound
    ```rs
    fn sdBunny(p: vec3f) -> f32 {
    if (dot(p, p) > 1.) { return length(p) - .8; }
    let q = vec4f(p, 1.);
    let f00=sin(mat4x4f(-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(mat4x4f(-.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(mat4x4f(-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(mat4x4f(-.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(mat4x4f(-.34,.06,-.59,-.76,.1,-.19,-.12,.44,.64,-.02,-.26,.15,-.16,.21,.91,.15)*f00+
    mat4x4f(.01,.54,-.77,.11,.06,-.14,.43,.51,-.18,.08,.39,.2,.33,-.49,-.1,.19)*f01+
    mat4x4f(.27,.22,.43,.53,.18,-.17,.23,-.64,-.14,.02,-.1,.16,-.13,-.06,-.04,-.36)*f02+
    mat4x4f(-.13,.29,-.29,.08,1.13,.02,-.83,.32,-.32,.04,-.31,-.16,.14,-.03,-.2,.39)*f03+
    vec4f(.73,-4.28,-1.56,-1.8))+f00;
    let f11=sin(mat4x4f(-1.11,.55,-.12,-1.00,.16,.15,-.3,.31,-.01,.01,.31,-.42,-.29,.38,-.04,.71)*f00+
    mat4x4f(.96,-.02,.86,.52,-.14,.6,.44,.43,.02,-.15,-.49,-.05,-.06,-.25,-.03,-.22)*f01+
    mat4x4f(.52,.44,-.05,-.11,-.56,-.1,-.61,-.4,-.04,.55,.32,-.07,-.02,.28,.26,-.49)*f02+
    mat4x4f(.02,-.32,.06,-.17,-.59,.00,-.24,.6,-.06,.13,-.21,-.27,-.12,-.14,.58,-.55)*f03+
    vec4f(-2.24,-3.48,-.8,1.41))+f01;
    let f12=sin(mat4x4f(.44,-.06,-.79,-.46,.05,-.6,.3,.36,.35,.12,.02,.12,.4,-.26,.63,-.21)*f00+
    mat4x4f(-.48,.43,-.73,-.4,.11,-.01,.71,.05,-.25,.25,-.28,-.2,.32,-.02,-.84,.16)*f01+
    mat4x4f(.39,-.07,.9,.36,-.38,-.27,-1.86,-.39,.48,-.2,-.05,.1,-.00,-.21,.29,.63)*f02+
    mat4x4f(.46,-.32,.06,.09,.72,-.47,.81,.78,.9,.02,-.21,.08,-.16,.22,.32,-.13)*f03+
    vec4f(3.38,1.2,.84,1.41))+f02;
    let f13=sin(mat4x4f(-.41,-.24,-.71,-.25,-.24,-.75,-.09,.02,-.27,-.42,.02,.03,-.01,.51,-.12,-1.24)*f00+
    mat4x4f(.64,.31,-1.36,.61,-.34,.11,.14,.79,.22,-.16,-.29,-.70,.02,-.37,.49,.39)*f01+
    mat4x4f(.79,.47,.54,-.47,-1.13,-.35,-1.03,-.22,-.67,-.26,.1,.21,-.07,-.73,-.11,.72)*f02+
    mat4x4f(.43,-.23,.13,.09,1.38,-.63,1.57,-.2,.39,-.14,.42,.13,-.57,-.08,-.21,.21)*f03+
    vec4f(-.34,-3.28,.43,-.52))+f03;
    let f20=sin(mat4x4f(-.72,.23,-.89,.52,.38,.19,-.16,-.88,.26,-.37,.09,.63,.29,-.72,.3,-.95)*f10+
    mat4x4f(-.22,-.51,-.42,-.73,-.32,.00,-1.03,1.17,-.2,-.03,-.13,-.16,-.41,.09,.36,-.84)*f11+
    mat4x4f(-.21,.01,.33,.47,.05,.2,-.44,-1.04,.13,.12,-.13,.31,.01,-.34,.41,-.34)*f12+
    mat4x4f(-.13,-.06,-.39,-.22,.48,.25,.24,-.97,-.34,.14,.42,-.00,-.44,.05,.09,-.95)*f13+
    vec4f(.48,.87,-.87,-2.06))/1.4+f10;
    let f21=sin(mat4x4f(-.27,.29,-.21,.15,.34,-.23,.85,-.09,-1.15,-.24,-.05,-.25,-.12,-.73,-.17,-.37)*f10+
    mat4x4f(-1.11,.35,-.93,-.06,-.79,-.03,-.46,-.37,.6,-.37,-.14,.45,-.03,-.21,.02,.59)*f11+
    mat4x4f(-.92,-.17,-.58,-.18,.58,.6,.83,-1.04,-.8,-.16,.23,-.11,.08,.16,.76,.61)*f12+
    mat4x4f(.29,.45,.3,.39,-.91,.66,-.35,-.35,.21,.16,-.54,-.63,1.1,-.38,.2,.15)*f13+
    vec4f(-1.72,-.14,1.92,2.08))/1.4+f11;
    let f22=sin(mat4x4f(1.00,.66,1.3,-.51,.88,.25,-.67,.03,-.68,-.08,-.12,-.14,.46,1.15,.38,-.1)*f10+
    mat4x4f(.51,-.57,.41,-.09,.68,-.5,-.04,-1.01,.2,.44,-.6,.46,-.09,-.37,-1.3,.04)*f11+
    mat4x4f(.14,.29,-.45,-.06,-.65,.33,-.37,-.95,.71,-.07,1.00,-.6,-1.68,-.2,-.00,-.7)*f12+
    mat4x4f(-.31,.69,.56,.13,.95,.36,.56,.59,-.63,.52,-.3,.17,1.23,.72,.95,.75)*f13+
    vec4f(-.9,-3.26,-.44,-3.11))/1.4+f12;
    let f23=sin(mat4x4f(.51,-.98,-.28,.16,-.22,-.17,-1.03,.22,.7,-.15,.12,.43,.78,.67,-.85,-.25)*f10+
    mat4x4f(.81,.6,-.89,.61,-1.03,-.33,.6,-.11,-.06,.01,-.02,-.44,.73,.69,1.02,.62)*f11+
    mat4x4f(-.1,.52,.8,-.65,.4,-.75,.47,1.56,.03,.05,.08,.31,-.03,.22,-1.63,.07)*f12+
    mat4x4f(-.18,-.07,-1.22,.48,-.01,.56,.07,.15,.24,.25,-.09,-.54,.23,-.08,.2,.36)*f13+
    vec4f(-1.11,-4.28,1.02,-.23))/1.4+f13;
    return dot(f20,vec4f(.09,.12,-.07,-.03))+dot(f21,vec4f(-.04,.07,-.08,.05))+
    dot(f22,vec4f(-.01,.06,-.02,.07))+dot(f23,vec4f(-.05,.07,.03,.04))- 0.16;
    }
    ```
    <img src="https://habrastorage.org/webt/17/20/f7/1720f7wtpzfovqvjrabg4q6qnxu.jpeg" width="150px">

    # Boolean operations with primitives

    #### Union, Subtraction, Intersection - exact (outside), bound, bound
  6. munrocket revised this gist Aug 7, 2023. 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
    @@ -449,7 +449,7 @@ fn opUnionChamfer(d1: f32, d2: f32, r: f32) -> f32 {
    return min(min(d1, d2), (d1 - r + d2) * 0.5);
    }

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

  7. munrocket revised this gist Aug 6, 2023. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,6 @@

    Revision: 06.08.2023, https://compute.toys/view/407

    # Primitives

    #### Sphere - exact
    ```rs
    fn sdSphere(p: vec3f, r: f32) -> f32 {
  8. munrocket revised this gist Aug 6, 2023. 1 changed file with 0 additions and 7 deletions.
    7 changes: 0 additions & 7 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -2,13 +2,6 @@

    Revision: 06.08.2023, https://compute.toys/view/407

    #### 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), [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. ???
    5. PROFIT

    # Primitives

    #### Sphere - exact
  9. munrocket revised this gist Aug 6, 2023. 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
    @@ -1,6 +1,6 @@
    # WGSL 3D SDF Primitives

    Revision: 06.08.2023
    Revision: 06.08.2023, https://compute.toys/view/407

    #### 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), [paper2](https://www.semanticscholar.org/paper/Enhanced-Sphere-Tracing-Keinert-Sch%C3%A4fer/4c9bd91bd044980f5746d623315be5285cc799c9), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
  10. munrocket revised this gist Aug 6, 2023. 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
    @@ -65,6 +65,7 @@ fn sdBoxFrame(p: vec3f, b: vec3f, e: f32) -> f32 {
    fn sdGyroid(p: vec3f, h: f32) -> f32 {
    return abs(dot(sin(p), cos(p.zxy))) - h;
    }
    //d = max(sdBox(p, vec3f(.8)), .5 * sdGyroid((p+vec3f(2.)) * 6.5, .2) / 6.5);
    ```
    <img src="https://habrastorage.org/webt/nu/mi/v9/numiv9d7cz6dfxrnkgripzbbai4.jpeg" width="150px">

  11. munrocket revised this gist Aug 6, 2023. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -165,7 +165,6 @@ fn sdInfiniteCylinder(p: vec3f, c: vec3f) -> f32 {
    fn sdCone(p: vec3f, h: f32, sincos: vec2f) -> f32 {
    // Alternatively pass q instead of (sin(alpha), cos(alpha))
    let q = h * vec2f(sincos.x / sincos.y, -1.);

    let w = vec2f(length(p.xz), p.y);
    let a = w - q * clamp(dot(w,q) / dot(q,q), 0., 1.);
    let b = w - q * vec2f(clamp(w.x / q.x, 0., 1.), 1.);
  12. munrocket revised this gist Aug 6, 2023. 1 changed file with 121 additions and 123 deletions.
    244 changes: 121 additions & 123 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -1,29 +1,27 @@
    # WGSL 3D SDF Primitives

    Revision: 06.08.2023

    #### 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), [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. ???
    5. PROFIT

    This code tested in Chrome and Firefox, should work on PC too.

    Function `select` can work differently in browsers.

    # Primitives

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

    #### Ellipsoid - bound (not exact)
    ```rs
    fn sdEllipsoid(p: vec3<f32>, r: vec3<f32>) -> f32 {
    fn sdEllipsoid(p: vec3f, r: vec3f) -> f32 {
    let k0 = length(p / r);
    let k1 = length(p / (r * r));
    return k0 * (k0 - 1.) / k1;
    @@ -33,56 +31,56 @@ fn sdEllipsoid(p: vec3<f32>, r: vec3<f32>) -> f32 {

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

    #### Round Box - exact
    ```rs
    fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    fn sdRoundBox(p: vec3f, b: vec3f, 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;
    return length(max(q, vec3f(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">

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

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

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

    #### Capped Torus - exact
    ```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);
    fn sdCappedTorus(p: vec3f, R: f32, r: f32, sincos: vec2f) -> f32 {
    let q = vec3f(abs(p.x), p.y, p.z);
    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;
    }
    @@ -91,16 +89,16 @@ fn sdCappedTorus(p: vec3<f32>, R: f32, r: f32, sincos: vec2<f32>) -> f32 {

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

    #### Capsule / Line - exact
    ```rs
    fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    fn sdCapsule(p: vec3f, a: vec3f, b: vec3f, r: f32) -> f32 {
    let pa = p - a;
    let ba = b - a;
    let h = clamp(dot(pa, ba) / dot(ba, ba), 0., 1.);
    @@ -111,16 +109,16 @@ fn sdCapsule(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {

    #### Vertical Capsule / Line - exact
    ```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);
    fn sdVerticalCapsule(p: vec3f, h: f32, r: f32) -> f32 {
    let q = vec3f(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">

    #### Cylinder - exact
    ```rs
    fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
    fn sdCylinder(p: vec3f, a: vec3f, b: vec3f, r: f32) -> f32 {
    let ba = b - a;
    let pa = p - a;
    let baba = dot(ba, ba);
    @@ -138,39 +136,39 @@ fn sdCylinder(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {

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

    #### Rounded Cylinder - exact
    ```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;
    fn sdRoundedCylinder(p: vec3f, h: f32, r: f32, re: f32) -> f32 {
    let d = vec2f(length(p.xz) - 2. * r + re, abs(p.y) - h);
    return min(max(d.x, d.y), 0.) + length(max(d, vec2f(0.))) - re;
    }
    ```
    <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 {
    fn sdInfiniteCylinder(p: vec3f, c: vec3f) -> f32 {
    return length(p.xz - c.xy) - c.z;
    }
    ```
    <img src="https://habrastorage.org/webt/bo/-p/pf/bo-ppfbsp71n1srnrclo3qc9tby.jpeg" width="150px">

    #### Cone - exact
    ```rs
    fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {
    fn sdCone(p: vec3f, h: f32, sincos: vec2f) -> f32 {
    // Alternatively pass q instead of (sin(alpha), cos(alpha))
    let q = h * vec2<f32>(sincos.x / sincos.y, -1.);
    let q = h * vec2f(sincos.x / sincos.y, -1.);

    let w = vec2<f32>(length(p.xz), p.y);
    let w = vec2f(length(p.xz), p.y);
    let a = w - q * clamp(dot(w,q) / dot(q,q), 0., 1.);
    let b = w - q * vec2<f32>(clamp(w.x / q.x, 0., 1.), 1.);
    let b = w - q * vec2f(clamp(w.x / q.x, 0., 1.), 1.);
    let k = sign(q.y);
    let d = min(dot(a, a), dot(b, b));
    let s = max(k * (w.x * q.y - w.y * q.x), k * (w.y - q.y));
    @@ -181,16 +179,16 @@ fn sdCone(p: vec3<f32>, h: f32, sincos: vec2<f32>) -> f32 {

    #### 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);
    fn sdConeBound(p: vec3f, h: f32, sincos: vec2f) -> f32 {
    return max(dot(sincos.yx, vec2f(length(p.xz), p.y)), -h - p.y);
    }
    ```
    <img src="https://habrastorage.org/webt/ie/lz/1h/ielz1hqyxdwhft2rt-x6333c478.jpeg" width="150px">

    #### Infinite Cone - exact
    ```rs
    fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {
    let q = vec2<f32>(length(p.xz), -p.y);
    fn sdInfiniteCone(p: vec3f, sincos: vec2f) -> f32 {
    let q = vec2f(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);
    }
    @@ -199,11 +197,11 @@ fn sdInfiniteCone(p: vec3<f32>, sincos: vec2<f32>) -> f32 {

    #### Capped Vertical Cone - exact
    ```rs
    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(r2, r1, q.y < 0.)), abs(q.y) - h);
    fn sdCappedVerticalCone(p: vec3f, h: f32, r1: f32, r2: f32) -> f32 {
    let q = vec2f(length(p.xz), p.y);
    let k1 = vec2f(r2, h);
    let k2 = vec2f(r2 - r1, 2. * h);
    let ca = vec2f(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.);
    return s * sqrt(min(dot(ca, ca), dot(cb, cb)));
    @@ -213,7 +211,7 @@ fn sdCappedVerticalCone(p: vec3<f32>, h: f32, r1: f32, r2: f32) -> f32 {

    #### Capped Cone - exact
    ```rs
    fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f32 {
    fn sdCappedCone(p: vec3f, a: vec3f, b: vec3f, ra: f32, rb: f32) -> f32 {
    let rba = rb - ra;
    let baba = dot(b - a, b - a);
    let papa = dot(p - a, p - a);
    @@ -233,21 +231,21 @@ fn sdCappedCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, ra: f32, rb: f32) -> f

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

    #### Round cone - exact
    ```rs
    fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f32 {
    fn sdRoundCone(p: vec3f, a: vec3f, b: vec3f, r1: f32, r2: f32) -> f32 {
    let ba = b - a;
    let l2 = dot(ba, ba);
    let rr = r1 - r2;
    @@ -272,8 +270,8 @@ fn sdRoundCone(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, r1: f32, r2: f32) -> f3

    #### Solid Angle - exact
    ```rs
    fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {
    let q = vec2<f32>(length(p.xz), p.y);
    fn sdSolidAngle(p: vec3f, sincos: vec2f, r: f32) -> f32 {
    let q = vec2f(length(p.xz), p.y);
    let l = length(q) - r;
    let m = length(q - sincos * clamp(dot(q, sincos), 0., r));
    return max(l, m * sign(sincos.y * q.x - sincos.x * q.y));
    @@ -283,7 +281,7 @@ fn sdSolidAngle(p: vec3<f32>, sincos: vec2<f32>, r: f32) -> f32 {

    #### Plane - exact
    ```rs
    fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {
    fn sdPlane(p: vec3f, n: vec3f, h: f32) -> f32 {
    // n must be normalized
    return dot(p, n) + h;
    }
    @@ -292,22 +290,22 @@ fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32 {

    #### Octahedron - exact
    ```rs
    fn sdOctahedron(p: vec3<f32>, s: f32) -> f32 {
    var q: vec3<f32> = abs(p);
    fn sdOctahedron(p: vec3f, s: f32) -> f32 {
    var q: vec3f = abs(p);
    let m = q.x + q.y + q.z - s;
    if (3. * q.x < m) {q = q.xyz;}
    else {if (3. * q.y < m) {q = q.yzx;}
    else {if (3. * q.z < m) {q = q.zxy;}
    else {return m * 0.57735027;}}}
    let k = clamp(0.5 * (q.z - q.y + s), 0., s);
    return length(vec3<f32>(q.x, q.y - s + k, q.z - k));
    return length(vec3f(q.x, q.y - s + k, q.z - k));
    }
    ```
    <img src="https://habrastorage.org/webt/pt/eg/rt/ptegrtffv6andxzppbgkzpl8poe.jpeg" width="150px">

    #### Octahedron - bound (not exact)
    ```rs
    fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {
    fn sdOctahedronBound(p: vec3f, s: f32) -> f32 {
    let q = abs(p);
    return (q.x + q.y + q.z - s) * 0.57735027;
    }
    @@ -316,13 +314,13 @@ fn sdOctahedronBound(p: vec3<f32>, s: f32) -> f32 {

    #### Pyramid - exact
    ```rs
    fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {
    fn sdPyramid(p: vec3f, h: f32) -> f32 {
    let m2 = h * h + 0.25;
    var xz: vec2<f32> = abs(p.xz);
    var xz: vec2f = abs(p.xz);
    xz = select(xz, xz.yx, xz[1] > xz[0]);
    xz = xz - vec2<f32>(0.5);
    xz = xz - vec2f(0.5);

    let q = vec3<f32>(xz[1], h * p.y - 0.5 * xz[0], h * xz[0] + 0.5 * p.y);
    let q = vec3f(xz[1], h * p.y - 0.5 * xz[0], h * xz[0] + 0.5 * p.y);
    let s = max(-q.x, 0.);
    let t = clamp((q.y - 0.5 * xz[1]) / (m2 + 0.25), 0., 1.);

    @@ -337,20 +335,20 @@ fn sdPyramid(p: vec3<f32>, h: f32) -> f32 {

    #### Hexagonal Prism - exact
    ```rs
    fn sdHexPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    let k = vec3<f32>(-0.8660254, 0.5, 0.57735);
    fn sdHexPrism(p: vec3f, h: vec2f) -> f32 {
    let k = vec3f(-0.8660254, 0.5, 0.57735);
    let a = abs(p);
    let v = a.xy - 2. * min(dot(k.xy, a.xy), 0.) * k.xy;
    let d1 = length(v - vec2<f32>(clamp(v.x, -k.z * h.x, k.z * h.x), h.x)) * sign(v.y - h.x);
    let d1 = length(v - vec2f(clamp(v.x, -k.z * h.x, k.z * h.x), h.x)) * sign(v.y - h.x);
    let d2 = a.z - h.y;
    return min(max(d1, d2), 0.) + length(max(vec2<f32>(d1, d2), vec2<f32>(0.)));
    return min(max(d1, d2), 0.) + length(max(vec2f(d1, d2), vec2f(0.)));
    }
    ```
    <img src="https://habrastorage.org/webt/tz/2i/3n/tz2i3na0oscwx1g_skclcoduo3o.jpeg" width="150px">

    #### Triangular Prism - bound
    ```rs
    fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {
    fn sdTriPrism(p: vec3f, h: vec2f) -> 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);
    }
    @@ -359,7 +357,7 @@ fn sdTriPrism(p: vec3<f32>, h: vec2<f32>) -> f32 {

    #### Quadratic Bezier - exact
    ```rs
    fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32> {
    fn sdBezier(p: vec3f, A: vec3f, B: vec3f, C: vec3f) -> vec2f {
    let a = B - A;
    let b = A - 2. * B + C;
    let c = a * 2.;
    @@ -374,27 +372,27 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>
    let q = kx * (2.0 * kx * kx - 3.0 * ky) + kz;
    var h: f32 = q * q + 4. * p3;

    var res: vec2<f32>;
    var res: vec2f;
    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 x = (vec2f(h, -h) - q) / 2.;
    let uv = sign(x) * pow(abs(x), vec2f(1. / 3.));
    let t = clamp(uv.x + uv.y - kx, 0., 1.);
    let f = d + (c + b * t) * t;
    res = vec2<f32>(dot(f, f), t);
    res = vec2f(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 t = clamp(vec2f(m + m, -n - m) * z - kx, vec2f(0.0), vec2f(1.0));
    let f = d + (c + b * t.x) * t.x;
    var dis: f32 = dot(f, f);
    res = vec2<f32>(dis, t.x);
    res = vec2f(dis, t.x);

    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 = select(res, vec2f(dis, t.y), dis < res.x);
    }
    res.x = sqrt(res.x);
    return res;
    @@ -404,7 +402,7 @@ fn sdBezier(p: vec3<f32>, A: vec3<f32>, B: vec3<f32>, C: vec3<f32>) -> vec2<f32>

    #### Triangle - exact
    ```rs
    fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {
    fn udTriangle(p: vec3f, a: vec3f, b: vec3f, c: vec3f) -> 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;
    @@ -423,7 +421,7 @@ fn udTriangle(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>) -> f32 {

    #### Quad - exact
    ```rs
    fn udQuad(p: vec3<f32>, a: vec3<f32>, b: vec3<f32>, c: vec3<f32>, d: vec3<f32>) -> f32 {
    fn udQuad(p: vec3f, a: vec3f, b: vec3f, c: vec3f, d: vec3f) -> 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;
    @@ -502,23 +500,23 @@ fn opDisplace(d1: f32, d2: f32) -> f32 {

    #### Twist - bound
    ```rs
    fn opTwist(p: vec3<f32>, k: f32) -> vec3<f32> {
    fn opTwist(p: vec3f, k: f32) -> vec3f {
    let s = sin(k * p.y);
    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);
    let m = mat2x2<f32>(vec2f(c, s), vec2f(-s, c));
    return vec3f(m * p.xz, p.y);
    }
    //let d = sdfPrimitive3d(opTwist(p, k));
    ```
    <img src="https://habrastorage.org/webt/9w/-e/5s/9w-e5spb9rqy41hepfwwqrfwd14.jpeg" width="150px">

    #### Bend - bound
    ```rs
    fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {
    fn opCheapBend(p: vec3f, k: f32) -> vec3f {
    let s = sin(k * p.x);
    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);
    let m = mat2x2<f32>(vec2f(c, s), vec2f(-s, c));
    return vec3f(m * p.xy, p.z);
    }
    //let d = sdfPrimitive3d(opCheapBend(p, k));
    ```
    @@ -528,7 +526,7 @@ fn opCheapBend(p: vec3<f32>, k: f32) -> vec3<f32> {

    #### Translate - exact
    ```rs
    fn opTranslate(p: vec3<f32>, t: vec3<f32>) -> vec3<f32> {
    fn opTranslate(p: vec3f, t: vec3f) -> vec3f {
    return p - t;
    }
    //let d = sdfPrimitive3d(opTranslate(p, t));
    @@ -537,54 +535,54 @@ fn opTranslate(p: vec3<f32>, t: vec3<f32>) -> vec3<f32> {

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

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

    fn op90RotateZ(p: vec3<f32>) -> vec3<f32> {
    return vec3<f32>(p.y, -p.x, p.z);
    fn op90RotateZ(p: vec3f) -> vec3f {
    return vec3f(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 around axis - exact
    ```rs
    fn opRotateX(p: vec3<f32>, a: f32) -> vec3<f32> {
    fn opRotateX(p: vec3f, a: f32) -> vec3f {
    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);
    return vec3f(p.x, c * p.y + s * p.z, -s * p.y + c * p.z);
    }

    fn opRotateY(p: vec3<f32>, a: f32) -> vec3<f32> {
    fn opRotateY(p: vec3f, a: f32) -> vec3f {
    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);
    return vec3f(c * p.x - s * p.z, p.y, s * p.x + c * p.z);
    }

    fn opRotateZ(p: vec3<f32>, a: f32) -> vec3<f32> {
    fn opRotateZ(p: vec3f, a: f32) -> vec3f {
    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);
    return vec3f(c * p.x + s * p.y, -s * p.x + c * p.y, p.z);
    }
    //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
    fn opRotateE(p: vec3<f32>, e: vec3<f32>, a: f32) -> vec3<f32> {
    fn opRotateE(p: vec3f, e: vec3f, a: f32) -> vec3f {
    let c = cos(a);
    return dot(e, p) * (1. - c) * e - cross(e, p) * sin(a) + c * p;
    }
    //let d = sdfPrimitive3d(opRotateE(p, normalize(vec3<f32>(1.,0.,.5)), a));
    //let d = sdfPrimitive3d(opRotateE(p, normalize(vec3f(1.,0.,.5)), a));
    ```
    <img src="https://habrastorage.org/webt/dj/ho/sc/djhoscnd2urd2envmjtplgdna7k.jpeg" width="150px"/>

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

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

    @@ -605,18 +603,18 @@ 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: vec3f) -> vec3f { return vec3f(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: vec3f) -> vec3f { return vec3f(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: vec3f) -> vec3f { return vec3f(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"/>

    #### Infinite Repetition - exact
    ```rs
    fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> vec3<f32> {
    fn opInfArray(p: vec3f, c: vec3f) -> vec3f {
    return p - c * round(p / c);
    }
    //let d = sdfPrimitive3d(opInfArray(p, c));
    @@ -625,7 +623,7 @@ fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> vec3<f32> {

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

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

    fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> vec4<f32> {
    fn opElongateCorrect(p: vec3f, h: vec3f) -> vec4f {
    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 sgn = 2. * step(vec3f(0.), p) - vec3f(1.);
    return vec4f(sgn * max(q, vec3f(0.)), min(max(q.x, max(q.y, q.z)), 0.));
    }
    //let p2 = opElongateCorrect(p, h);
    //let d = p2.w + sdfPrimitive3d(p2.xyz);
    @@ -653,7 +651,7 @@ fn opElongateCorrect(p: vec3<f32>, h: vec3<f32>) -> vec4<f32> {

    #### Rounding - exact
    ```rs
    fn opRound(p: vec3<f32>, r: f32) -> f32 {
    fn opRound(p: vec3f, r: f32) -> f32 {
    return sdfPrimitive3d(p) - r;
    }
    ```
    @@ -671,38 +669,38 @@ fn opOnion(d: f32, thickness: f32) -> f32 {
    #### Extrusion from 2D SDF - exact
    ```rs
    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 w = vec2f(d, abs(z) - h);
    return min(max(w.x, w.y), 0.) + length(max(w, vec2f(0.)));
    }
    //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
    fn opRevolution(p: vec3<f32>, o: f32) -> vec2<f32> {
    return vec2<f32>(length(p.xz) - o, p.y);
    fn opRevolution(p: vec3f, o: f32) -> vec2f {
    return vec2f(length(p.xz) - o, p.y);
    }
    //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 length4(p: vec3<f32>) -> f32 {
    var q: vec3<f32> = p * p;
    fn length4(p: vec3f) -> f32 {
    var q: vec3f = p * p;
    q = q * q;
    return sqrt(sqrt(q.x + q.y + q.z));
    }

    fn length6(p: vec3<f32>) -> f32 {
    var q: vec3<f32> = p * p * p;
    fn length6(p: vec3f) -> f32 {
    var q: vec3f = p * p * p;
    q = q * q;
    return pow(q.x + q.y + q.z, 1. / 6.);
    }

    fn length8(p: vec3<f32>) -> f32 {
    var q: vec3<f32> = p * p;
    fn length8(p: vec3f) -> f32 {
    var q: vec3f = p * p;
    q = q * q; q = q * q;
    return pow(q.x + q.y + q.z, 1. / 8.);
    }
  13. munrocket revised this gist Oct 23, 2022. 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
    @@ -1,4 +1,4 @@
    # 3D SDF Primitives in WGSL
    # WGSL 3D SDF Primitives

    #### 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), [paper2](https://www.semanticscholar.org/paper/Enhanced-Sphere-Tracing-Keinert-Sch%C3%A4fer/4c9bd91bd044980f5746d623315be5285cc799c9), [youtube](https://www.youtube.com/watch?v=PGtv-dBi2wE))
  14. munrocket revised this gist Oct 12, 2021. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -542,7 +542,6 @@ fn op90RotateX(p: vec3<f32>) -> vec3<f32> {
    }

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

  15. munrocket revised this gist Aug 31, 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
    @@ -9,7 +9,7 @@

    This code tested in Chrome and Firefox, should work on PC too.

    Functions `select` and `%` can work differently in browsers.
    Function `select` can work differently in browsers.

    # Primitives

    @@ -618,7 +618,7 @@ fn opSymmetryZ(p: vec3<f32>) -> vec3<f32> { return vec3<f32>(p.x, p.y, abs(p.z))
    #### Infinite Repetition - exact
    ```rs
    fn opInfArray(p: vec3<f32>, c: vec3<f32>) -> vec3<f32> {
    return (p + 0.5 * c % c) - 0.5 * c;
    return p - c * round(p / c);
    }
    //let d = sdfPrimitive3d(opInfArray(p, c));
    ```
    @@ -710,4 +710,4 @@ fn length8(p: vec3<f32>) -> f32 {
    ```
    <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
    MIT License. © 2020 Inigo Quilez, Johann Korndörfer, Martijn Steinrucken, Munrocket
  16. munrocket revised this gist Aug 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
    @@ -8,7 +8,8 @@
    5. PROFIT

    This code tested in Chrome and Firefox, should work on PC too.
    WGSL is not stable functions `select` and `%` can works differently in browsers.

    Functions `select` and `%` can work differently in browsers.

    # Primitives

  17. munrocket revised this gist Aug 18, 2021. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions wgsl_3d_sdf.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,8 @@
    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.
    WGSL is not stable functions `select` and `%` can works differently in browsers.

    # Primitives

    @@ -708,4 +709,4 @@ fn length8(p: vec3<f32>) -> f32 {
    ```
    <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
    MIT License. © 2020 Munrocket, Inigo Quilez, Johann Korndörfer, Martijn Steinrucken
  18. 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
  19. 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"/>
  20. 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);
  21. 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;
  22. 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;
  23. 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
  24. 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
  25. 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;
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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 {