Created
January 27, 2019 17:36
-
-
Save sebastien/44e4f88a2cfba489864a1a0b513e9d0d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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