Skip to content

Commit

Permalink
feat(shader-ast): add/update sdf fns, fix fogExp2, update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jun 18, 2019
1 parent b4ca8e4 commit d5115ff
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 19 deletions.
42 changes: 42 additions & 0 deletions packages/shader-ast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ This project is part of the
- [Installation](#installation)
- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [API](#api)
- [Supported types](#supported-types)
- [Operators](#operators)
- [Symbol definitions / assignments](#symbol-definitions--assignments)
- [Control flow](#control-flow)
- [Built-in functions](#built-in-functions)
- [User defined functions](#user-defined-functions)
- [Code generation](#code-generation)
- [Compilation & execution](#compilation--execution)
- [AST tooling & traversal](#ast-tooling--traversal)
- [Authors](#authors)
- [License](#license)

Expand Down Expand Up @@ -106,6 +116,8 @@ Benefits of this approach:
- [ ] integration w/
[@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl)
- [ ] boilerplate for JS runtime (non-GPU shader execution)
- [ ] AST transformations (optimizers, e.g. [constant
folding](https://github.com/thi-ng/umbrella/tree/feature/webgl/packages/shader-ast/src/optimize.ts))

## Installation

Expand All @@ -129,6 +141,36 @@ yarn add @thi.ng/shader-ast
- [raymarch shader](https://demo.thi.ng/umbrella/shader-ast-raymarch/), [source code](https://github.com/thi-ng/umbrella/tree/feature/webgl/examples/shader-ast-raymarch)
- [tunnel shader](https://demo.thi.ng/umbrella/shader-ast-tunnel/), [source code](https://github.com/thi-ng/umbrella/tree/feature/webgl/examples/shader-ast-tunnel)

## API

TODO

### Supported types

### Operators

#### Swizzling

#### Index lookups

### Symbol definitions / assignments

### Control flow

### Built-in functions

### User defined functions

#### Inline functions

### Code generation

### Compilation & execution

### AST tooling & traversal

#### Tree optimizations

## Authors

- Karsten Schmidt
Expand Down
2 changes: 1 addition & 1 deletion packages/shader-ast/src/std/fog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const fogExp2 = defn(
ret(
sub(
F32_1,
clamp01(exp2(mul(mul(density, density), float(1 / Math.LOG2E))))
clamp01(exp2(mul(mul(density, density), float(-Math.LOG2E))))
)
)
]
Expand Down
180 changes: 162 additions & 18 deletions packages/shader-ast/src/std/sdf.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Sym } from "../api";
import { Sym, Term } from "../api";
import {
$,
add,
defn,
div,
F32_0,
F32_1,
float,
mul,
neg,
ret,
Expand All @@ -20,11 +21,58 @@ import {
length,
max,
min,
mix
mix,
mod
} from "../builtins";
import { clamp01 } from "./clamp";
import { fit1101 } from "./fit";

// Signed Distance Field primitives and operations based on work by
// Inigo Quilezles (iq).
//
// Reference:
//
// - http://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
// - http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm

//////////////// 2D primitives

/**
* Returns signed distance from `p` to centered circle of radius `r`.
*
* @param p vec3
* @param r f32
*/
export const sdCircle = defn("f32", "sdCircle", [["vec2"], ["f32"]], (p, r) => [
ret(sub(length(p), r))
]);

/**
* Returns signed distance from `p` to centered circle of radius `r`.
*
* @param p vec3
* @param r f32
*/
export const sdLine2 = defn("f32", "sdLine2", [["vec2"], ["f32"]], (p, r) => [
ret(sub(length(p), r))
]);

/**
* Returns signed distance from `p` to centered AABB of `size`.
*
* @param p vec3
* @param size vec3
*/
export const sdRect = defn("f32", "sdRect", [["vec2"], ["vec2"]], (p, size) => {
let d: Sym<"vec2">;
return [
(d = sym(sub(abs(p), size))),
ret(add(min(max($(d, "x"), $(d, "y")), F32_0), length(max(d, vec2()))))
];
});

//////////////// 3D primitives

/**
* Returns signed distance from `p` to plane.
*
Expand Down Expand Up @@ -117,30 +165,31 @@ export const sdCylinder = defn(
* @param p vec3
* @param a vec3
* @param b vec3
* @param r f32
*/
export const sdCapsule = defn(
export const sdLine3 = defn(
"f32",
"sdCapsule",
[["vec3"], ["vec3"], ["vec3"], ["f32"]],
(p, a, b, r) => {
"sdLine3",
[["vec3"], ["vec3"], ["vec3"]],
(p, a, b) => {
let pa: Sym<"vec3">, ba: Sym<"vec3">, h: Sym<"f32">;
return [
(pa = sym(sub(p, a))),
(ba = sym(sub(b, a))),
(h = sym(clamp01(div(dot(pa, ba), dot(ba, ba))))),
ret(sub(length(mul(sub(pa, ba), h)), r))
ret(length(mul(sub(pa, ba), h)))
];
}
);

//////////////// Combinators

/**
* @param d1 f32
* @param d2 f32
*/
export const sdSubtract = defn(
export const sdOpSubtract = defn(
"f32",
"sdSubtract",
"sdOpSubtract",
[["f32"], ["f32"]],
(d1, d2) => [ret(max(neg(d2), d1))]
);
Expand All @@ -149,23 +198,118 @@ export const sdSubtract = defn(
* @param d1 f32
* @param d2 f32
*/
export const sdUnion = defn("f32", "sdUnion", [["f32"], ["f32"]], (d1, d2) => [
ret(min(d1, d2))
]);
export const sdOpUnion = defn(
"f32",
"sdOpUnion",
[["f32"], ["f32"]],
(d1, d2) => [ret(min(d1, d2))]
);

/**
* @param d1 f32
* @param d2 f32
*/
export const sdBlend = defn(
export const sdOpIntersect = defn(
"f32",
"sdBlend",
"sdOpIntersect",
[["f32"], ["f32"]],
(d1, d2) => [ret(max(d2, d1))]
);

/**
* @param d1 f32
* @param d2 f32
*/
export const sdOpSmoothUnion = defn(
"f32",
"sdOpSmoothUnion",
[["f32"], ["f32"], ["f32"]],
(a, b, f) => {
(a, b, k) => {
let h: Sym<"f32">;
return [
(h = sym(clamp01(fit1101(div(sub(b, a), f))))),
ret(sub(mix(b, a, h), mul(mul(f, h), sub(F32_1, h))))
(h = sym(clamp01(fit1101(div(sub(b, a), k))))),
ret(sub(mix(b, a, h), mul(mul(k, h), sub(F32_1, h))))
];
}
);

/**
* @param d1 f32
* @param d2 f32
*/
export const sdOpSmoothSubtract = defn(
"f32",
"sdOpSmoothSubtract",
[["f32"], ["f32"], ["f32"]],
(a, b, k) => {
let h: Sym<"f32">;
return [
(h = sym(clamp01(fit1101(div(add(b, a), k))))),
ret(add(mix(b, neg(a), h), mul(mul(k, h), sub(F32_1, h))))
];
}
);

/**
* @param d1 f32
* @param d2 f32
*/
export const sdOpSmoothIntersect = defn(
"f32",
"sdOpSmoothIntersect",
[["f32"], ["f32"], ["f32"]],
(a, b, k) => {
let h: Sym<"f32">;
return [
(h = sym(clamp01(fit1101(div(sub(b, a), k))))),
ret(add(mix(b, a, h), mul(mul(k, h), sub(F32_1, h))))
];
}
);

/**
* Inline function. Essentially an isoline offset to create:
*
* - `r > 0`: rounded/thicker shapes
* - `r < 0`: sharper/thinner shapes
*
* @param d
* @param r
*/
export const sdOpRound = (d: Term<"f32">, r: Term<"f32">) => sub(d, r);

/**
* Inline function. Bi-directional offset to create ring like shapes.
*
* @param d
* @param r
*/
export const sdOpAnnular = (d: Term<"f32">, r: Term<"f32">) => sub(abs(d), r);

//////////////// Transformations

/**
* Domain repetition by wrapping position `p` into period `c`.
*
* @param p vec2
* @param c vec2
*/
export const sdTxRepeat2 = defn(
"vec2",
"sdTxRepeat3",
[["vec2"], ["vec2"]],
(p, c) => [ret(sub(mod(p, c), mul(c, float(0.5))))]
);

/**
* Domain repetition by wrapping position `p` into period `c`.
*
* @param p vec3
* @param c vec3
*/
export const sdTxRepeat3 = defn(
"vec3",
"sdTxRepeat3",
[["vec3"], ["vec3"]],
(p, c) => [ret(sub(mod(p, c), mul(c, float(0.5))))]
);

0 comments on commit d5115ff

Please sign in to comment.