Skip to content

Commit

Permalink
Enhance Worley noise with solid cells option (#2119)
Browse files Browse the repository at this point in the history
Adds a new control to `worley2d` and `worley3d`, which allows artists to choose between a distance for each cell (the default) and solid values for each cell. This allows for more patterns to be expressed in materials (i.e. flakes).
  • Loading branch information
crydalch authored Dec 14, 2024
1 parent ecd3479 commit e5a9e35
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 47 deletions.
2 changes: 2 additions & 0 deletions documents/Specification/MaterialX.Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -888,12 +888,14 @@ Standard Noise nodes:

* **`worleynoise2d`**: 2D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
* `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0.
* `style` (integer): the output style, one of "distance" (distance to the cell center), or "solid" (constant value for each cell).
* `texcoord` (vector2): the 2D position at which the noise is evaluated. Default is to use the first set of texture coordinates.

<a id="node-worleynoise3d"> </a>

* **`worleynoise3d`**: 3D Worley noise using centered jitter, outputting float (distance metric to closest feature), vector2 (distance metrics to closest 2 features) or vector3 (distance metrics to closest 3 features).
* `jitter` (float): amount to jitter the cell center position, with smaller values creating a more regular pattern. Default is 1.0.
* `style` (integer): the output style, one of "distance" (distance to the cell center), or "solid" (constant value for each cell). Default is "distance".
* `position` (vector3): the 3D position at which the noise is evaluated. Default is to use the current 3D object-space coordinate.

<a id="node-unifiednoise2d"> </a>
Expand Down
141 changes: 106 additions & 35 deletions libraries/stdlib/genglsl/lib/mx_noise.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -437,16 +437,32 @@ vec4 mx_fractal_noise_vec4(vec3 p, int octaves, float lacunarity, float diminish
return vec4(c, f);
}

float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric)
vec2 mx_worley_cell_position(int x, int y, int xoff, int yoff, float jitter)
{
vec3 tmp = mx_cell_noise_vec3(vec2(x+xoff, y+yoff));
vec2 off = vec2(tmp.x, tmp.y);

off -= 0.5f;
off *= jitter;
off += 0.5f;

return vec2(float(x), float(y)) + off;
}

vec3 mx_worley_cell_position(int x, int y, int z, int xoff, int yoff, int zoff, float jitter)
{
vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff));

off -= 0.5f;
off *= jitter;
off += 0.5f;

return vec3(float(x), float(y), float(z)) + off;
}

vec2 cellpos = vec2(float(x), float(y)) + off;
float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric)
{
vec2 cellpos = mx_worley_cell_position(x, y, xoff, yoff, jitter);
vec2 diff = cellpos - p;
if (metric == 2)
return abs(diff.x) + abs(diff.y); // Manhattan distance
Expand All @@ -458,13 +474,7 @@ float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter,

float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zoff, float jitter, int metric)
{
vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff));

off -= 0.5f;
off *= jitter;
off += 0.5f;

vec3 cellpos = vec3(float(x), float(y), float(z)) + off;
vec3 cellpos = mx_worley_cell_position(x, y, z, xoff, yoff, zoff, jitter);
vec3 diff = cellpos - p;
if (metric == 2)
return abs(diff.x) + abs(diff.y) + abs(diff.z); // Manhattan distance
Expand All @@ -474,65 +484,91 @@ float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zo
return dot(diff, diff);
}

float mx_worley_noise_float(vec2 p, float jitter, int metric)
float mx_worley_noise_float(vec2 p, float jitter, int style, int metric)
{
int X, Y;
float dist;
vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
float sqdist = 1e6f; // Some big number for jitter > 1 (not all GPUs may be IEEE)
vec2 minpos = vec2(0,0);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
sqdist = min(sqdist, dist);
vec2 cellpos = mx_worley_cell_position(x, y, X, Y, jitter) - localpos;
if(dist < sqdist)
{
sqdist = dist;
minpos = cellpos;
}
}
}
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
return mx_cell_noise_float(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vec2 mx_worley_noise_vec2(vec2 p, float jitter, int metric)
vec2 mx_worley_noise_vec2(vec2 p, float jitter, int style, int metric)
{
int X, Y;
vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
vec2 sqdist = vec2(1e6f, 1e6f);
vec2 minpos = vec2(0,0);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
vec2 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)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
{
vec3 tmp = mx_cell_noise_vec3(minpos + p);
return vec2(tmp.x,tmp.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vec3 mx_worley_noise_vec3(vec2 p, float jitter, int metric)
vec3 mx_worley_noise_vec3(vec2 p, float jitter, int style, int metric)
{
int X, Y;
vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
vec3 sqdist = vec3(1e6f, 1e6f, 1e6f);
vec2 minpos = vec2(0,0);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
vec2 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)
{
Expand All @@ -545,48 +581,67 @@ vec3 mx_worley_noise_vec3(vec2 p, float jitter, int metric)
}
}
}
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
return mx_cell_noise_vec3(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

float mx_worley_noise_float(vec3 p, float jitter, int metric)
float mx_worley_noise_float(vec3 p, float jitter, int style, int metric)
{
int X, Y, Z;
vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
float sqdist = 1e6f;
vec3 minpos = vec3(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 dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
sqdist = min(sqdist, dist);
vec3 cellpos = mx_worley_cell_position(x, y, z, X, Y, Z, jitter) - localpos;
if(dist < sqdist)
{
sqdist = dist;
minpos = cellpos;
}
}
}
}
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
return mx_cell_noise_float(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vec2 mx_worley_noise_vec2(vec3 p, float jitter, int metric)
vec2 mx_worley_noise_vec2(vec3 p, float jitter, int style, int metric)
{
int X, Y, Z;
vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
vec2 sqdist = vec2(1e6f, 1e6f);
vec3 minpos = vec3(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 dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
vec3 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)
{
Expand All @@ -595,28 +650,39 @@ vec2 mx_worley_noise_vec2(vec3 p, float jitter, int metric)
}
}
}
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
{
vec3 tmp = mx_cell_noise_vec3(minpos + p);
return vec2(tmp.x,tmp.y);
}
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}

vec3 mx_worley_noise_vec3(vec3 p, float jitter, int metric)
vec3 mx_worley_noise_vec3(vec3 p, float jitter, int style, int metric)
{
int X, Y, Z;
vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
vec3 sqdist = vec3(1e6f, 1e6f, 1e6f);
vec3 minpos = vec3(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 dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
vec3 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)
{
Expand All @@ -630,7 +696,12 @@ vec3 mx_worley_noise_vec3(vec3 p, float jitter, int metric)
}
}
}
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
if (style == 1)
return mx_cell_noise_vec3(minpos + p);
else
{
if (metric == 0)
sqdist = sqrt(sqdist);
return sqdist;
}
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise2d_float.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise2d_float(vec2 texcoord, float jitter, out float result)
void mx_worleynoise2d_float(vec2 texcoord, float jitter, int style, out float result)
{
result = mx_worley_noise_float(texcoord, jitter, 0);
result = mx_worley_noise_float(texcoord, jitter, style, 0);
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise2d_vector2.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise2d_vector2(vec2 texcoord, float jitter, out vec2 result)
void mx_worleynoise2d_vector2(vec2 texcoord, float jitter, int style, out vec2 result)
{
result = mx_worley_noise_vec2(texcoord, jitter, 0);
result = mx_worley_noise_vec2(texcoord, jitter, style, 0);
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise2d_vector3.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise2d_vector3(vec2 texcoord, float jitter, out vec3 result)
void mx_worleynoise2d_vector3(vec2 texcoord, float jitter, int style, out vec3 result)
{
result = mx_worley_noise_vec3(texcoord, jitter, 0);
result = mx_worley_noise_vec3(texcoord, jitter, style, 0);
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise3d_float.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise3d_float(vec3 position, float jitter, out float result)
void mx_worleynoise3d_float(vec3 position, float jitter, int style, out float result)
{
result = mx_worley_noise_float(position, jitter, 0);
result = mx_worley_noise_float(position, jitter, style, 0);
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise3d_vector2.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise3d_vector2(vec3 position, float jitter, out vec2 result)
void mx_worleynoise3d_vector2(vec3 position, float jitter, int style, out vec2 result)
{
result = mx_worley_noise_vec2(position, jitter, 0);
result = mx_worley_noise_vec2(position, jitter, style, 0);
}
4 changes: 2 additions & 2 deletions libraries/stdlib/genglsl/mx_worleynoise3d_vector3.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "lib/mx_noise.glsl"

void mx_worleynoise3d_vector3(vec3 position, float jitter, out vec3 result)
void mx_worleynoise3d_vector3(vec3 position, float jitter, int style, out vec3 result)
{
result = mx_worley_noise_vec3(position, jitter, 0);
result = mx_worley_noise_vec3(position, jitter, style, 0);
}
6 changes: 6 additions & 0 deletions libraries/stdlib/stdlib_defs.mtlx
Original file line number Diff line number Diff line change
Expand Up @@ -1002,16 +1002,19 @@
<nodedef name="ND_worleynoise2d_float" node="worleynoise2d" nodegroup="procedural2d">
<input name="texcoord" type="vector2" defaultgeomprop="UV0" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="float" default="0.0" />
</nodedef>
<nodedef name="ND_worleynoise2d_vector2" node="worleynoise2d" nodegroup="procedural2d">
<input name="texcoord" type="vector2" defaultgeomprop="UV0" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="vector2" default="0.0, 0.0" />
</nodedef>
<nodedef name="ND_worleynoise2d_vector3" node="worleynoise2d" nodegroup="procedural2d">
<input name="texcoord" type="vector2" defaultgeomprop="UV0" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="vector3" default="0.0, 0.0, 0.0" />
</nodedef>

Expand All @@ -1022,16 +1025,19 @@
<nodedef name="ND_worleynoise3d_float" node="worleynoise3d" nodegroup="procedural3d">
<input name="position" type="vector3" defaultgeomprop="Pobject" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="float" default="0.0" />
</nodedef>
<nodedef name="ND_worleynoise3d_vector2" node="worleynoise3d" nodegroup="procedural3d">
<input name="position" type="vector3" defaultgeomprop="Pobject" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="vector2" default="0.0, 0.0" />
</nodedef>
<nodedef name="ND_worleynoise3d_vector3" node="worleynoise3d" nodegroup="procedural3d">
<input name="position" type="vector3" defaultgeomprop="Pobject" />
<input name="jitter" type="float" value="1.0" />
<input name="style" uiname="Cell Style" type="integer" value="0" enum="Distance,Solid" enumvalues="0,1" />
<output name="out" type="vector3" default="0.0, 0.0, 0.0" />
</nodedef>

Expand Down

0 comments on commit e5a9e35

Please sign in to comment.