Skip to content

Instantly share code, notes, and snippets.

@sebastien
Created January 27, 2019 17:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebastien/44e4f88a2cfba489864a1a0b513e9d0d to your computer and use it in GitHub Desktop.
Save sebastien/44e4f88a2cfba489864a1a0b513e9d0d to your computer and use it in GitHub Desktop.
let
hash2x2 xy = frac([262144, 32768] * sin(dot(xy, [41, 289])));
// TODO: Rephrase in a more functional style, compose passes for clarity.
// TODO: The voronoi input should be a vec3
// TODO: There seems to be some odd artifacts
//matrix (n,m) = [for (i in 0..<floor(n*m)) [mod(i,n),floor(i/n)] ];
between(v,a,b) = if (a <= v && v <= b) 0.0 else 1.0;
prel(v,a,b) = (v - a)/(b - a);
rescale(v,a,b) = lerp(b[0],b[1],prel(v,a[0],a[1]));
// Points cannot be closer than sqrt(EPSILON)
EPSILON = .00001;
// input: 2D coordinate, output: distance to cell border
// FIXME: x is actually xy
voronoi p =
let
x = [p[0],p[1]];
z = p[2];
// Each cell is 1.5 units wide, so we get the "cell origin"
n = floor(x-1.5);
// F becomes the delta to the "origin", ie our relative position
// in the cell.
f = x - n;
in do
// first pass: distance to cell centre
var mr := [0,0];
var md := 8;
// A noise cell is 3x3 units
// TODO: Refactor in a purely functional style.
for (j in 0 .. 3)
for (i in 0 .. 3) do
// G is the delta on a the 3x3 grid
var g := [i,j] ;
// O is independent from F, in other words, it is fixed
// within the cell. These are the "random feature points"
// that we're evaluating. O is actually a displacement. Multiply
// it by 0 and you get a grid.
var o := hash2x2(n + g) ;
// G is our position within the 3x3 grid, modulated by the
// displacement O. The squared length is going to be the dot
// product of the distance between F (the current coordinate
// within the cell) and the feature point.
var r := f - (o + g);
var d := dot(r,r);
in
// We're basically getting the minimum distance for all of these.
if (d < md) (
md := d;
mr := r;
);
// second pass: distance to border
md := 8.0;
// NOTE: Adjusting the 3 argument changes the size/depth of the
// holes.
var mk := rescale(z, [0,1], [0.91,0.2]);
for (j in 0 .. 3)
for (i in 0 .. 3) do
var g := [i,j];
var o := hash2x2( n + g );
var r := f - (o + g);
in (
// Up to here that's pretty much the same as above: get the 3x3
// feature point matrix in cell-relative coordinate.
if (dot(mr-r,mr-r)>EPSILON) // skip the same cell
md := smooth_min(md, dot(0.5*(mr+r), normalize(r-mr)), mk);
);
in md;
voronoi3d = make_shape {
// FIXME: This seems quite weird
dist (x,y,z,t) = voronoi ([x,y,z]);
is_2d = true;
is_3d = true;
};
zlimit = make_shape {
dist (x,y,z,t) = between(z,0,1);
is_2d = true;
is_3d = true;
}
in
intersection(
zlimit,
cube >> scale 3,
voronoi3d
)
// EOF -- vim: ts=4 sw=4 noet syn=javascript
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment