Skip to content

Commit

Permalink
Update OSL Worley noise implementation (#2155)
Browse files Browse the repository at this point in the history
#2119 added a new `style` parameter to Worley noise - this PR adds corresponding support to the OSL backend - mirroring behavior from the GLSL code generator.
  • Loading branch information
ld-kerley authored Dec 29, 2024
1 parent 73f5f39 commit 894b479
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 86 deletions.
269 changes: 189 additions & 80 deletions libraries/stdlib/genosl/include/mx_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,36 +356,41 @@ vector4 mx_fbm(point position, int octaves, float lacunarity, float diminish, st
return vector4 (c[0], c[1], c[2], f);
}

vector2 mx_worley_cell_position(int x, int y, int xoff, int yoff, float jitter)
{
vector tmp = cellnoise(x+xoff, y+yoff);
vector2 off = vector2(tmp.x, tmp.y);
off -= 0.5;
off *= jitter;
off += 0.5;
return vector2(x, y) + off;
}

void mx_split_float(output float x, output int ix)
vector mx_worley_cell_position(int x, int y, int z, int xoff, int yoff, int zoff, float jitter)
{
ix = int(floor(x));
x -= ix;
vector off = cellnoise(vector(x+xoff, y+yoff, z+zoff));
off -= 0.5;
off *= jitter;
off += 0.5;
return vector(x,y,z) + off;
}

float mx_worley_distance(vector2 p, int x, int y, int X, int Y, float jitter, int metric)
{
vector o = cellnoise(x+X, y+Y);
o = (o - .5)*jitter + .5;
float cposx = x + o[0];
float cposy = y + o[1];
float diffx = cposx - p.x;
float diffy = cposy - p.y;
vector2 cellpos = mx_worley_cell_position(x,y,X,Y,jitter);
vector2 diff = cellpos - p;

if (metric == 2)
return abs(diffx) + abs(diffy); // Manhattan distance
return abs(diff.x) + abs(diff.y); // Manhattan distance
if (metric == 3)
return max(abs(diffx), abs(diffy)); // Chebyshev distance
return diffx*diffx + diffy*diffy; // Euclidean or distance^2
return max(abs(diff.x), abs(diff.y)); // Chebyshev distance
return diff.x*diff.x + diff.y*diff.y; // Euclidean or distance^2
}

float mx_worley_distance(vector p, int x, int y, int z, int X, int Y, int Z, float jitter, int metric)
{
vector o = cellnoise(vector(x+X, y+Y, z+Z));
o = (o - .5)*jitter + .5;
vector cpos = vector(x, y, z) + o;
vector diff = cpos - p;

vector cellpos = mx_worley_cell_position(x,y,z,X,Y,Z,jitter);
vector diff = cellpos - p;
if (metric == 2)
return abs(diff[0]) + abs(diff[1]); // Manhattan distance
if (metric == 3)
Expand Down Expand Up @@ -425,140 +430,244 @@ void mx_sort_distance(float dist, output vector result)
}
}

float mx_worley_noise_float(vector2 p, float jitter, int metric)
// return floor as well as the fractional remainder
float mx_floorfrac(float x, output int i)
{
i = (int)floor(x);
return x - float(i);
}

float mx_worley_noise_float(vector2 p, float jitter, int style, int metric)
{
int X, Y;
vector2 seed = p;
float result = 1e6;
float sqdist = 1e6;
vector2 localpos = vector2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
vector2 minpos = vector2(0.0, 0.0);

mx_split_float(seed.x, X);
mx_split_float(seed.y, Y);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float d = mx_worley_distance(seed, x, y, X, Y, jitter, metric);
result = min(result, d);
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
vector2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos;
if (dist < sqdist)
{
sqdist = dist;
minpos = cellpos;
}
}
}
if (metric == 0)
result = sqrt(result);
return result;
if (style == 1)
{
vector2 tmpP = minpos + p;
return cellnoise(tmpP.x, tmpP.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vector2 mx_worley_noise_vector2(vector2 p, float jitter, int metric)
vector2 mx_worley_noise_vector2(vector2 p, float jitter, int style, int metric)
{
int X, Y;
vector2 seed = p;
vector2 result = vector2(1e6, 1e6);
vector2 sqdist = vector2(1e6, 1e6);
vector2 localpos = vector2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
vector2 minpos = vector2(0.0, 0.0);

mx_split_float(seed.x, X);
mx_split_float(seed.y, Y);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float d = mx_worley_distance(seed, x, y, X, Y, jitter, metric);
mx_sort_distance(d, result);
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
vector2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos;
if (dist < sqdist.x)
{
sqdist.y = sqdist.x;
sqdist.x = dist;
minpos = cellpos;
}
else if (dist < sqdist.y)
{
sqdist.y = dist;
}
}
}
if (metric == 0)
result = sqrt(result);
return result;

if (style == 1)
{
vector2 tmpP = minpos + p;
vector tmp = cellnoise(tmpP.x, tmpP.y);
return vector2(tmp.x, tmp.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vector mx_worley_noise_vector3(vector2 p, float jitter, int metric)
vector mx_worley_noise_vector3(vector2 p, float jitter, int style, int metric)
{
int X, Y;
vector2 seed = p;
vector result = vector(1e6, 1e6, 1e6);
vector sqdist = vector(1e6, 1e6, 1e6);
vector2 localpos = vector2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
vector2 minpos = vector2(0.0, 0.0);

mx_split_float(seed.x, X);
mx_split_float(seed.y, Y);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float d = mx_worley_distance(seed, x, y, X, Y, jitter, metric);
mx_sort_distance(d, result);
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
vector2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos;
if (dist < sqdist.x)
{
sqdist.z = sqdist.y;
sqdist.y = sqdist.x;
sqdist.x = dist;
minpos = cellpos;
}
else if (dist < sqdist.y)
{
sqdist.z = sqdist.y;
sqdist.y = dist;
}
else if (dist < sqdist.z)
{
sqdist.z = dist;
}
}
}
if (metric == 0)
result = sqrt(result);
return result;
if (style == 1)
{
vector2 tmpP = minpos + p;
return cellnoise(tmpP.x, tmpP.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

float mx_worley_noise_float(vector p, float jitter, int metric)
float mx_worley_noise_float(vector p, float jitter, int style, int metric)
{
int X, Y, Z;
vector seed = p;
float result = 1e6;

mx_split_float(seed[0], X);
mx_split_float(seed[1], Y);
mx_split_float(seed[2], Z);
float sqdist = 1e6;
vector localpos = vector(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
vector minpos = vector(0.0, 0.0, 0.0);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
for (int z = -1; z <= 1; ++z)
{
float d = mx_worley_distance(seed, x, y, z, X, Y, Z, jitter, metric);
result = min(result, d);
float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
vector cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos;
if(dist < sqdist)
{
sqdist = dist;
minpos = cellpos;
}
}
}
}
if (metric == 0)
result = sqrt(result);
return result;
if (style == 1)
return cellnoise(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vector2 mx_worley_noise_vector2(vector p, float jitter, int metric)
vector2 mx_worley_noise_vector2(vector p, float jitter, int style, int metric)
{
int X, Y, Z;
vector seed = p;
vector2 result = vector2(1e6, 1e6);
vector2 sqdist = vector2(1e6, 1e6);
vector localpos = vector(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
vector minpos = vector(0.0, 0.0, 0.0);

mx_split_float(seed[0], X);
mx_split_float(seed[1], Y);
mx_split_float(seed[2], Z);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
for (int z = -1; z <= 1; ++z)
{
float d = mx_worley_distance(seed, x, y, z, X, Y, Z, jitter, metric);
mx_sort_distance(d, result);
float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
vector cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos;
if (dist < sqdist.x)
{
sqdist.y = sqdist.x;
sqdist.x = dist;
minpos = cellpos;
}
else if (dist < sqdist.y)
{
sqdist.y = dist;
}
}
}
}
if (metric == 0)
result = sqrt(result);
return result;
if (style == 1)
{
vector tmp = cellnoise(minpos + p);
return vector2(tmp.x,tmp.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vector mx_worley_noise_vector3(vector p, float jitter, int metric)
vector mx_worley_noise_vector3(vector p, float jitter, int style, int metric)
{
int X, Y, Z;
vector result = 1e6;
vector seed = p;
vector sqdist = 1e6;
vector localpos = vector(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
vector minpos = vector(0.0, 0.0, 0.0);

mx_split_float(seed[0], X);
mx_split_float(seed[1], Y);
mx_split_float(seed[2], Z);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
for (int z = -1; z <= 1; ++z)
{
float d = mx_worley_distance(seed, x, y, z, X, Y, Z, jitter, metric);
mx_sort_distance(d, result);
float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
vector cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos;
if (dist < sqdist.x)
{
sqdist.z = sqdist.y;
sqdist.y = sqdist.x;
sqdist.x = dist;
minpos = cellpos;
}
else if (dist < sqdist.y)
{
sqdist.z = sqdist.y;
sqdist.y = dist;
}
else if (dist < sqdist.z)
{
sqdist.z = dist;
}
}
}
}
if (metric == 0)
result = sqrt(result);
return result;
if (style == 1)
return cellnoise(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}
2 changes: 1 addition & 1 deletion libraries/stdlib/genosl/mx_worleynoise2d_float.osl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void mx_worleynoise2d_float(vector2 texcoord, float jitter, int style, output float result)
{
result = mx_worley_noise_float(texcoord, jitter, 0);
result = mx_worley_noise_float(texcoord, jitter, style, 0);
}
2 changes: 1 addition & 1 deletion libraries/stdlib/genosl/mx_worleynoise2d_vector2.osl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void mx_worleynoise2d_vector2(vector2 texcoord, float jitter, int style, output vector2 result)
{
result = mx_worley_noise_vector2(texcoord, jitter, 0);
result = mx_worley_noise_vector2(texcoord, jitter, style, 0);
}
2 changes: 1 addition & 1 deletion libraries/stdlib/genosl/mx_worleynoise2d_vector3.osl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void mx_worleynoise2d_vector3(vector2 texcoord, float jitter, int style, output vector result)
{
result = mx_worley_noise_vector3(texcoord, jitter, 0);
result = mx_worley_noise_vector3(texcoord, jitter, style, 0);
}
2 changes: 1 addition & 1 deletion libraries/stdlib/genosl/mx_worleynoise3d_float.osl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void mx_worleynoise3d_float(vector position, float jitter, int style, output float result)
{
result = mx_worley_noise_float(position, jitter, 0);
result = mx_worley_noise_float(position, jitter, style, 0);
}
2 changes: 1 addition & 1 deletion libraries/stdlib/genosl/mx_worleynoise3d_vector2.osl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
void mx_worleynoise3d_vector2(vector position, float jitter, int style, output vector2 result)
{
result = mx_worley_noise_vector2(position, jitter, 0);
result = mx_worley_noise_vector2(position, jitter, style, 0);
}
Loading

0 comments on commit 894b479

Please sign in to comment.