Skip to content

Commit

Permalink
feat(shader-ast-stdlib): add more 2D SDF prims
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed May 6, 2022
1 parent 59d631a commit 2672e75
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 0 deletions.
18 changes: 18 additions & 0 deletions packages/shader-ast-stdlib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,27 @@
"./sdf/annular": {
"default": "./sdf/annular.js"
},
"./sdf/arc": {
"default": "./sdf/arc.js"
},
"./sdf/bezier": {
"default": "./sdf/bezier.js"
},
"./sdf/box-rounded": {
"default": "./sdf/box-rounded.js"
},
"./sdf/box": {
"default": "./sdf/box.js"
},
"./sdf/cross": {
"default": "./sdf/cross.js"
},
"./sdf/cylinder": {
"default": "./sdf/cylinder.js"
},
"./sdf/hex": {
"default": "./sdf/hex.js"
},
"./sdf/isec": {
"default": "./sdf/isec.js"
},
Expand All @@ -254,6 +269,9 @@
"./sdf/plane": {
"default": "./sdf/plane.js"
},
"./sdf/polygon": {
"default": "./sdf/polygon.js"
},
"./sdf/polyhedra": {
"default": "./sdf/polyhedra.js"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/shader-ast-stdlib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ export * from "./sdf/annular.js";
export * from "./sdf/arc.js";
export * from "./sdf/bezier.js";
export * from "./sdf/box.js";
export * from "./sdf/box-rounded.js";
export * from "./sdf/cross.js";
export * from "./sdf/cylinder.js";
export * from "./sdf/hex.js";
export * from "./sdf/isec.js";
export * from "./sdf/line.js";
export * from "./sdf/mirror.js";
export * from "./sdf/plane.js";
export * from "./sdf/polyhedra.js";
export * from "./sdf/polygon.js";
export * from "./sdf/repeat.js";
export * from "./sdf/repeat-polar.js";
export * from "./sdf/round.js";
Expand Down
36 changes: 36 additions & 0 deletions packages/shader-ast-stdlib/src/sdf/box-rounded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { FloatSym, Vec2Sym } from "@thi.ng/shader-ast";
import { ternary } from "@thi.ng/shader-ast/ast/controlflow";
import { defn, ret } from "@thi.ng/shader-ast/ast/function";
import { FLOAT0, VEC2_0 } from "@thi.ng/shader-ast/ast/lit";
import { add, gt, sub } from "@thi.ng/shader-ast/ast/ops";
import { $, $x, $xy, $y } from "@thi.ng/shader-ast/ast/swizzle";
import { sym } from "@thi.ng/shader-ast/ast/sym";
import { abs, length, max, min } from "@thi.ng/shader-ast/builtin/math";
import { maxComp2 } from "../math/maxcomp.js";

/**
* Returns signed distance from `p` to centered 2D rect of `size` and corner
* radii defined by given vec4 `r`.
*
* @remarks
* Ported from original GLSL impl by Inigo Quilez:
* - https://iquilezles.org/articles/distfunctions2d/
*
* @param p - vec2
* @param size - vec2
* @param r - vec4
*/
export const sdfBoxRounded = defn(
"float",
"sdfBoxRounded",
["vec2", "vec2", "vec4"],
(p, size, r) => {
let q: Vec2Sym, t: Vec2Sym, d: FloatSym;
return [
(t = sym(ternary(gt($x(p), FLOAT0), $xy(r), $(r, "zw")))),
(d = sym(ternary(gt($y(p), FLOAT0), $x(t), $y(t)))),
(q = sym(add(sub(abs(p), size), d))),
ret(sub(add(min(maxComp2(q), FLOAT0), length(max(q, VEC2_0))), d)),
];
}
);
75 changes: 75 additions & 0 deletions packages/shader-ast-stdlib/src/sdf/cross.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { FloatSym, Vec2Sym } from "@thi.ng/shader-ast/api/syms";
import { assign } from "@thi.ng/shader-ast/ast/assign";
import { ifThen, ternary } from "@thi.ng/shader-ast/ast/controlflow";
import { defn, ret } from "@thi.ng/shader-ast/ast/function";
import { FLOAT0, FLOAT05, vec2, VEC2_0 } from "@thi.ng/shader-ast/ast/lit";
import { add, gt, madd, mul, neg, sub } from "@thi.ng/shader-ast/ast/ops";
import { $, $x, $y } from "@thi.ng/shader-ast/ast/swizzle";
import { sym } from "@thi.ng/shader-ast/ast/sym";
import { abs, length, max, min, sign } from "@thi.ng/shader-ast/builtin/math";
import { maxComp2 } from "../math/maxcomp.js";

/**
* Returns signed distance from `p` to 2D cross/plus of given `size` and corner
* radius `r`.
*
* @remarks
* - `size` consist of overall width/size (in x) and thickness (in y component)
* - corner radius can also be negative
*
* Ported from original GLSL impl by Inigo Quilez:
* - https://iquilezles.org/articles/distfunctions2d/
*
* @param p -
* @param size -
* @param r -
*/
export const sdfCross2 = defn(
"float",
"sdfCross2",
["vec2", "vec2", "float"],
(p, size, r) => {
let a: Vec2Sym, q: Vec2Sym, w: Vec2Sym;
let k: FloatSym;
return [
(a = sym(abs(p))),
ifThen(gt($y(a), $x(a)), [assign(a, $(a, "yx"))]),
(q = sym(sub(a, size))),
(k = sym(maxComp2(q))),
(w = sym(
ternary(gt(k, FLOAT0), q, vec2(sub($y(size), $x(a)), neg(k)))
)),
ret(madd(sign(k), length(max(w, VEC2_0)), r)),
];
}
);

/**
* Returns signed distance from `p` to 2D "X-sign" of given `size` and stroke
* weight `r`.
*
* @remarks
* Ported from original GLSL impl by Inigo Quilez:
* - https://iquilezles.org/articles/distfunctions2d/
*
* @param p -
* @param size -
* @param r -
*/
export const sdfRoundedX2 = defn(
"float",
"sdfRoundedX",
["vec2", "float", "float"],
(p, size, r) => {
let q: Vec2Sym;
return [
(q = sym(abs(p))),
ret(
sub(
length(sub(q, mul(min(add($x(q), $y(q)), size), FLOAT05))),
r
)
),
];
}
);
43 changes: 43 additions & 0 deletions packages/shader-ast-stdlib/src/sdf/hex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { Vec2Sym } from "@thi.ng/shader-ast/api/syms";
import { assign } from "@thi.ng/shader-ast/ast/assign";
import { defn, ret } from "@thi.ng/shader-ast/ast/function";
import { FLOAT0, vec2 } from "@thi.ng/shader-ast/ast/lit";
import { mul, sub } from "@thi.ng/shader-ast/ast/ops";
import { $x, $y } from "@thi.ng/shader-ast/ast/swizzle";
import { sym } from "@thi.ng/shader-ast/ast/sym";
import {
abs,
clamp,
dot,
length,
min,
sign,
} from "@thi.ng/shader-ast/builtin/math";

/**
* Returns signed distance from `p` to 2D hexagon of given radius `r`.
*
* @remarks
* Ported from original GLSL impl by Inigo Quilez:
* - https://iquilezles.org/articles/distfunctions2d/
*/
export const sdfHexagon2 = defn(
"float",
"sdfHexagon2",
["vec2", "float"],
(p, r) => {
const TAN30 = 0.5773502691896257;
let k: Vec2Sym, q: Vec2Sym;
return [
// sin/cos @ 60deg
(k = sym(vec2(-0.8660254037844386, 0.5))),
(q = sym(abs(p))),
assign(q, sub(q, mul(k, mul(2, min(dot(k, q), FLOAT0))))),
assign(
q,
sub(q, vec2(clamp($x(q), mul(r, -TAN30), mul(r, TAN30)), r))
),
ret(mul(length(q), sign($y(q)))),
];
}
);
78 changes: 78 additions & 0 deletions packages/shader-ast-stdlib/src/sdf/polygon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { BVec3Sym, FloatSym, IntSym, Vec2Sym } from "@thi.ng/shader-ast";
import { assign } from "@thi.ng/shader-ast/ast/assign";
import { forLoop, ifThen } from "@thi.ng/shader-ast/ast/controlflow";
import { defn, ret } from "@thi.ng/shader-ast/ast/function";
import { index } from "@thi.ng/shader-ast/ast/indexed";
import { bvec3, FLOAT1, int, INT0 } from "@thi.ng/shader-ast/ast/lit";
import {
div,
gt,
gte,
inc,
lt,
mul,
neg,
not,
or,
sub,
} from "@thi.ng/shader-ast/ast/ops";
import { $x, $y } from "@thi.ng/shader-ast/ast/swizzle";
import { sym } from "@thi.ng/shader-ast/ast/sym";
import { all, _any } from "@thi.ng/shader-ast/builtin/bvec";
import { dot, min, sqrt } from "@thi.ng/shader-ast/builtin/math";
import { clamp01 } from "../math/clamp.js";

/**
* Higher-order function. Returns specialized function to compute signed
* distance for 2D polygons of `N` vertices.
*
* @remarks
* Based on original GLSL impl by Inigo Quilez:
* - https://iquilezles.org/articles/distfunctions2d/
*
* @param N
*/
export const sdfPolygon2 = (N: number) =>
defn(
"float",
`sdfPolygon2_${N}`,
["vec2", ["vec2[]", "pts", { num: N }]],
(p, pts) => {
let d: FloatSym, s: FloatSym;
let b: Vec2Sym, e: Vec2Sym, w: Vec2Sym, t: Vec2Sym;
let pi: Vec2Sym, pj: Vec2Sym;
let c: BVec3Sym;
let j: IntSym;
return [
(t = sym(sub(p, index(pts, 0)))),
(d = sym(dot(t, t))),
(s = sym(FLOAT1)),
(j = sym(int(N - 1))),
forLoop(
sym(INT0),
(i) => lt(i, int(N)),
inc,
(i) => [
(pi = sym(index(pts, i))),
(pj = sym(index(pts, j))),
(e = sym(sub(pj, pi))),
(w = sym(sub(p, pi))),
(b = sym(
sub(w, mul(e, clamp01(div(dot(w, e), dot(e, e)))))
)),
assign(d, min(d, dot(b, b))),
(c = sym(
bvec3(
gte($y(p), $y(pi)),
lt($y(p), $y(pj)),
gt(mul($x(e), $y(w)), mul($y(e), $x(w)))
)
)),
ifThen(or(all(c), not(_any(c))), [assign(s, neg(s))]),
assign(j, i),
]
),
ret(mul(s, sqrt(d))),
];
}
);

0 comments on commit 2672e75

Please sign in to comment.