Skip to content

Commit

Permalink
feat(shader-ast-stdlib): add new fns, various refactoring, add docs
Browse files Browse the repository at this point in the history
- add clamp11(), orthogonal(), rayPointAt()
- split lambert() / halfLambert()
- switch to more inline fns
  • Loading branch information
postspectacular committed Jul 1, 2019
1 parent fb5141e commit b215055
Show file tree
Hide file tree
Showing 17 changed files with 179 additions and 78 deletions.
8 changes: 1 addition & 7 deletions packages/shader-ast-stdlib/src/fog/exp2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
assign,
defn,
exp2,
float,
FLOAT1,
mul,
ret,
Expand All @@ -20,11 +19,6 @@ export const fogExp2 = defn(
[["float"], ["float"]],
(dist, density) => [
assign(density, mul(density, dist)),
ret(
sub(
FLOAT1,
clamp01(exp2(mul(mul(density, density), float(-Math.LOG2E))))
)
)
ret(sub(FLOAT1, clamp01(exp2(mul(mul(density, density), -Math.LOG2E)))))
]
);
2 changes: 2 additions & 0 deletions packages/shader-ast-stdlib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from "./math/cross2";
export * from "./math/fit";
export * from "./math/maxcomp";
export * from "./math/mincomp";
export * from "./math/orthogonal";

export * from "./matrix/lookat";
export * from "./matrix/mvp";
Expand All @@ -20,6 +21,7 @@ export * from "./matrix/normal";
export * from "./raymarch/ao";
export * from "./raymarch/direction";
export * from "./raymarch/normal";
export * from "./raymarch/point-at";
export * from "./raymarch/scene";

export * from "./screen/uv";
Expand Down
57 changes: 29 additions & 28 deletions packages/shader-ast-stdlib/src/lighting/lambert.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
import {
add,
defn,
dot,
FloatSym,
FLOAT0,
FloatTerm,
madd,
max,
mul,
ret,
sym,
ternary
Vec3Term
} from "@thi.ng/shader-ast";
import { fit1101 } from "../math/fit";

/**
* Computes Lambert term, optionally using Half-Lambertian,
* if `half` is true.
*
* https://developer.valvesoftware.com/wiki/Half_Lambert
* Inline function. Computes Lambert term, i.e. max(dot(n,l), 0). Both
* vectors must be pre-normalized.
*
* @param surfNormal vec3
* @param lightDir vec3
* @param half bool
*/
export const lambert = defn(
"float",
"lambert",
[["vec3"], ["vec3"], ["bool"]],
(n, ldir, bidir) => {
let d: FloatSym;
return [(d = sym(dot(n, ldir))), ret(ternary(bidir, fit1101(d), d))];
}
);
export const lambert = (n: Vec3Term, ldir: Vec3Term) =>
max(dot(n, ldir), FLOAT0);

/**
* Inline function. Computes Half-Lambertian term. Both vectors must be
* pre-normalized.
*
* https://developer.valvesoftware.com/wiki/Half_Lambert
*
* @param n
* @param ldir
*/
export const halfLambert = (n: Vec3Term, ldir: Vec3Term) =>
fit1101(dot(n, ldir));

/**
* Inline function. Computes: col = lambert * light * diffuse + ambient
*
* @param lambertian float
* @param diffuseCol vec3
* @param lightCol vec3
* @param ambientCol vec3
*/
export const diffuseLighting = defn(
"vec3",
"diffuseLighting",
[["float"], ["vec3"], ["vec3"], ["vec3"]],
(lambertian, diffuse, light, ambient) => [
ret(mul(diffuse, add(mul(light, lambertian), ambient)))
]
);
export const diffuseLighting = (
lambertian: FloatTerm,
diffuse: Vec3Term,
light: Vec3Term,
ambient: Vec3Term
) => madd(mul(light, lambertian), diffuse, ambient);
17 changes: 17 additions & 0 deletions packages/shader-ast-stdlib/src/math/clamp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
clamp,
float,
FLOAT0,
FLOAT1,
FloatTerm,
Expand Down Expand Up @@ -28,3 +29,19 @@ export const clamp01 = <T extends Prim>(x: Term<T>): Term<T> =>
? clamp(<Vec3Term>x, vec3(), vec3(1))
: clamp(<Vec4Term>x, vec4(), vec4(1)))
);

/**
* Inline function, expands to equivalent of `clamp(x, -1, 1)`.
*
* @param x
*/
export const clamp11 = <T extends Prim>(x: Term<T>): Term<T> =>
<Term<any>>(
(x.type === "float"
? clamp(<FloatTerm>x, float(-1), FLOAT1)
: x.type === "vec2"
? clamp(<Vec2Term>x, vec2(-1), vec2(1))
: x.type === "vec3"
? clamp(<Vec3Term>x, vec3(-1), vec3(1))
: clamp(<Vec4Term>x, vec4(-1), vec4(1)))
);
17 changes: 17 additions & 0 deletions packages/shader-ast-stdlib/src/math/cross2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,26 @@ import {
Vec2Term
} from "@thi.ng/shader-ast";

/**
* Inline function. Computes 2D cross product of given vectors.
*
* @see crossC2
*
* @param a
* @param b
*/
export const cross2 = (a: Vec2Term, b: Vec2Term) =>
crossC2($x(a), $y(a), $x(b), $y(b));

/**
* Inline function. Computes 2D cross product of given individual
* components: ax * by - ay * bx
*
* @param ax
* @param ay
* @param bx
* @param by
*/
export const crossC2 = (
ax: FloatTerm,
ay: FloatTerm,
Expand Down
9 changes: 5 additions & 4 deletions packages/shader-ast-stdlib/src/math/fit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
FLOAT05,
FLOAT1,
FLOAT2,
mix,
mul,
Op2,
Prim,
Expand All @@ -11,18 +12,18 @@ import {
} from "@thi.ng/shader-ast";

/**
* Fits value `a` in [0..1] interval to new interval [b..c]. No clamping
* performed.
* Inline function. Fits value `a` in [0..1] interval to new interval
* [b..c]. No clamping performed. Same as `mix(b, c, a)`
*
* @param a
* @param b
* @param c
*/
export const fit01 = <A extends Prim, B extends A, C extends A>(
export const fit01 = <A extends Prim, B extends A, C extends B>(
a: Term<A>,
b: Term<B>,
c: Term<C>
): Op2<A> => <any>add(<any>b, mul(sub(<any>b, c), a));
) => mix<A, A, A>(b, c, a);

/**
* Inline function. Fits value `x` in [-1..+1] interval to [0..1]
Expand Down
15 changes: 15 additions & 0 deletions packages/shader-ast-stdlib/src/math/maxcomp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@ import {
Vec4Sym
} from "@thi.ng/shader-ast";

/**
* Inline function. Returns max(v.x, v.y)
*
* @param v
*/
export const maxComp2 = (v: Vec2Sym | Vec3Sym | Vec4Sym) => max($x(v), $y(v));

/**
* Inline function. Returns max(v.x, v.y, v.z)
*
* @param v
*/
export const maxComp3 = (v: Vec3Sym | Vec4Sym) => max(maxComp2(v), $z(v));

/**
* Inline function. Returns max(v.x, v.y, v.z, v.w)
*
* @param v
*/
export const maxComp4 = (v: Vec4Sym) => max(maxComp3(v), $w(v));
15 changes: 15 additions & 0 deletions packages/shader-ast-stdlib/src/math/mincomp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,23 @@ import {
Vec4Sym
} from "@thi.ng/shader-ast";

/**
* Inline function. Returns min(v.x, v.y)
*
* @param v
*/
export const minComp2 = (v: Vec2Sym | Vec3Sym | Vec4Sym) => min($x(v), $y(v));

/**
* Inline function. Returns min(v.x, v.y, v.z)
*
* @param v
*/
export const minComp3 = (v: Vec3Sym | Vec4Sym) => min(minComp2(v), $z(v));

/**
* Inline function. Returns min(v.x, v.y, v.z, v.w)
*
* @param v
*/
export const minComp4 = (v: Vec4Sym) => min(minComp3(v), $w(v));
27 changes: 27 additions & 0 deletions packages/shader-ast-stdlib/src/math/orthogonal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
$x,
$y,
$z,
abs,
defn,
gt,
neg,
ret,
ternary,
vec3
} from "@thi.ng/shader-ast";

/**
* Returns an orthogonal vector to `v`.
*
* http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts
*/
export const orthogonal = defn("vec3", "orthogonal", [["vec3"]], (v) => [
ret(
ternary(
gt(abs($x(v)), abs($z(v))),
vec3(neg($y(v)), $x(v), 0),
vec3(0, neg($z(v)), $y(v))
)
)
]);
1 change: 1 addition & 0 deletions packages/shader-ast-stdlib/src/matrix/normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Vec3Term,
vec4
} from "@thi.ng/shader-ast";

/**
* Inline function. Multiplies `normal` with given 4x4 normal matrix
* (e.g. transpose inverse of view * model).
Expand Down
2 changes: 1 addition & 1 deletion packages/shader-ast-stdlib/src/raymarch/ao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const raymarchAO = (scene: RaymarchScene, numSamples = 5) =>
(i) => lte(i, float(numSamples)),
(i) => inc(i),
(i) => [
(d0 = sym(mul(i, float(1 / numSamples)))),
(d0 = sym(mul(i, 1 / numSamples))),
assign(
r,
add(r, mul(w, sub(d0, $x(scene(add(p, mul(n, d0)))))))
Expand Down
2 changes: 1 addition & 1 deletion packages/shader-ast-stdlib/src/raymarch/normal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { RaymarchScene } from "../api";
export const raymarchNormal = (scene: RaymarchScene, name = "raymarchNormal") =>
defn("vec3", name, [["vec3"], ["float"]], (p, smooth) => {
let dn: Vec2Sym;
let comp = (id: Swizzle2_3) =>
const comp = (id: Swizzle2_3) =>
sub($x(scene(add(p, $(dn, id)))), $x(scene(sub(p, $(dn, id)))));
return [
(dn = sym(vec2(smooth, 0))),
Expand Down
25 changes: 25 additions & 0 deletions packages/shader-ast-stdlib/src/raymarch/point-at.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
add,
FloatTerm,
mul,
normalize,
Term,
Vec
} from "@thi.ng/shader-ast";

/**
* Inline function. Returns point on ray (`p`, `dir`) at distance `t`.
* Unless `norm` is true (default false), `dir` must be already
* normalized.
*
* @param p
* @param dir
* @param t
* @param normalize
*/
export const rayPointAt = <A extends Vec, B extends A>(
p: Term<A>,
dir: Term<B>,
t: FloatTerm,
norm = false
) => add(p, mul(norm ? normalize(dir) : dir, t));
10 changes: 5 additions & 5 deletions packages/shader-ast-stdlib/src/raymarch/scene.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
$x,
$y,
add,
assign,
brk,
defn,
Expand All @@ -13,13 +12,14 @@ import {
inc,
int,
lt,
mul,
madd,
ret,
sym,
vec2,
Vec2Sym
} from "@thi.ng/shader-ast";
import { RaymarchOpts, RaymarchScene } from "../api";
import { rayPointAt } from "./point-at";

/**
* Higher order function producing a function to perform a raymarch
Expand All @@ -43,7 +43,7 @@ export const raymarchScene = (
_opts?: Partial<RaymarchOpts>
) => {
const opts: RaymarchOpts = {
name: "raymarch",
name: "raymarchScene",
near: 0.1,
far: 10,
steps: 100,
Expand All @@ -62,11 +62,11 @@ export const raymarchScene = (
(i) => lt(i, int(opts.steps)),
(i) => inc(i),
() => [
assign(res, scene(add(pos, mul(dir, total)))),
assign(res, scene(rayPointAt(pos, dir, total))),
ifThen(lt($x(res), float(opts.eps)), [
ret(vec2(total, $y(res)))
]),
assign(total, add(total, mul($x(res), float(opts.bias)))),
assign(total, madd($x(res), float(opts.bias), total)),
ifThen(gt(total, float(opts.far)), [brk])
]
),
Expand Down
15 changes: 6 additions & 9 deletions packages/shader-ast-stdlib/src/sdf/isec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { defn, max, ret } from "@thi.ng/shader-ast";
import { FloatTerm, max } from "@thi.ng/shader-ast";

/**
* @param d1 float
* @param d2 float
* Inline function. SDF shape intersection (a & b).
*
* @param a float
* @param b float
*/
export const sdfIntersect = defn(
"float",
"sdOpIntersect",
[["float"], ["float"]],
(d1, d2) => [ret(max(d2, d1))]
);
export const sdfIntersect = (a: FloatTerm, b: FloatTerm) => max(b, a);
Loading

0 comments on commit b215055

Please sign in to comment.