Node: Gabor Noise Texture #110802

Open
Charlie Jolly wants to merge 68 commits from CharlieJolly/blender:gabor into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 86 additions and 82 deletions
Showing only changes of commit d190aa3a71 - Show all commits

View File

@ -49,12 +49,12 @@ struct FractalParams {
float rot_lacunarity;
};
int impulses_per_cell(vector3 cell, float impulses)
int impulses_per_cell(vector3 cell, float impulses, int seed)
{
int n = int(impulses);
float rmd = impulses - floor(impulses);
if (rmd > 0.0) {
float t = hash_vector3_to_float(cell);
float t = hash_vector4_to_float(vector4(cell[0], cell[1], cell[2], float(seed - GABOR_SEED)));
if (t <= rmd) {
return n + 1;
}
@ -134,14 +134,14 @@ vector gabor_sample(GaborParams gp, vector3 cell, int seed, output float phi)
gp.anisotropy);
}
vector3 gabor_cell_3d(output GaborParams gp, point cell, point cell_position)
vector3 gabor_cell_3d(output GaborParams gp, point cell, point cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
vector3 sum = vector3(0.0);
for (int i = 0; i < num_impulses; ++i) {
vector3 rand_position = mix(
vector3(0.0),
hash_vector4_to_color(vector4(cell[0], cell[1], cell[2], float(i * GABOR_SEED))),
hash_vector4_to_color(vector4(cell[0], cell[1], cell[2], float(seed + i * GABOR_SEED))),
gp.cell_randomness);
point kernel_position = (cell_position - rand_position);
@ -150,21 +150,21 @@ vector3 gabor_cell_3d(output GaborParams gp, point cell, point cell_position)
if (dv <= 1.0) {
float phi;
vector3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
vector3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
return sum;
}
vector3 gabor_cell_2d(output GaborParams gp, point cell, point cell_position)
vector3 gabor_cell_2d(output GaborParams gp, point cell, point cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
vector3 sum = vector3(0.0);
for (int i = 0; i < num_impulses; ++i) {
vector3 rand_position = mix(
vector3(0.0),
hash_vector4_to_color(vector4(cell[0], cell[1], cell[2], float(i * GABOR_SEED))),
hash_vector4_to_color(vector4(cell[0], cell[1], cell[2], float(seed + i * GABOR_SEED))),
gp.cell_randomness);
rand_position.z = 0.0;
@ -174,7 +174,7 @@ vector3 gabor_cell_2d(output GaborParams gp, point cell, point cell_position)
if (dv <= 1.0) {
float phi;
vector3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
vector3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
@ -186,7 +186,7 @@ float gabor_coord_wrap(float a, float b)
return (b != 0.0) ? a - b * floor(a / b) : 0.0;
}
float gabor_grid_3d(output GaborParams gp, point p, float scale, int periodic)
float gabor_grid_3d(output GaborParams gp, point p, float scale, int periodic, int seed)
{
point coords = p * scale;
point position = floor(coords);
@ -212,7 +212,7 @@ float gabor_grid_3d(output GaborParams gp, point p, float scale, int periodic)
cell[2] = gabor_coord_wrap(cell[2], scale);
}
sum += gabor_cell_3d(gp, cell, cell_position);
sum += gabor_cell_3d(gp, cell, cell_position, seed);
}
}
}
@ -228,7 +228,7 @@ float gabor_grid_3d(output GaborParams gp, point p, float scale, int periodic)
}
}
float gabor_grid_2d(output GaborParams gp, point p, float scale, int periodic)
float gabor_grid_2d(output GaborParams gp, point p, float scale, int periodic, int seed)
{
point coords = point(p.x, p.y, 0.0) * scale;
point position = floor(coords);
@ -252,7 +252,7 @@ float gabor_grid_2d(output GaborParams gp, point p, float scale, int periodic)
cell[1] = gabor_coord_wrap(cell[1], scale);
}
sum += gabor_cell_2d(gp, cell, cell_position);
sum += gabor_cell_2d(gp, cell, cell_position, seed);
}
}
@ -316,9 +316,9 @@ float gabor_fractal_noise(FractalParams fp,
}
int n = int(octaves);
for (int i = 0; i <= n; i++) {
vector3 co = p + float(use_origin_offset * i * GABOR_SEED);
float t = (dimensions == "3D") ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * i * GABOR_SEED;
float t = (dimensions == "3D") ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
gp.frequency *= fp.fre_lacunarity;
gp.rotation -= fp.rot_lacunarity;
sum += t * amp;
@ -328,9 +328,9 @@ float gabor_fractal_noise(FractalParams fp,
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
vector3 co = p + float(use_origin_offset * (n + 1) * GABOR_SEED);
float t = (dimensions == "3D") ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * (n + 1) * GABOR_SEED;
float t = (dimensions == "3D") ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
float sum2 = sum + t * amp;
return mix(sum, sum2, rmd) * gp.gain / maxamp;
}

View File

@ -43,12 +43,12 @@ typedef struct FractalParams {
float rot_lacunarity;
} FractalParams;
ccl_device int impulses_per_cell(float3 cell, float impulses)
ccl_device int impulses_per_cell(float3 cell, float impulses, int seed)
{
int n = int(impulses);
float rmd = impulses - floorf(impulses);
if (rmd > 0.0f) {
float t = hash_float3_to_float(cell);
float t = hash_float4_to_float(make_float4(cell.x, cell.y, cell.z, float(seed - GABOR_SEED)));
return (t <= rmd) ? n + 1 : n;
}
return n;
@ -124,14 +124,14 @@ ccl_device float3 gabor_sample(GaborParams gp, float3 cell, int seed, ccl_privat
gp.anisotropy);
}
ccl_device float3 gabor_cell_3d(GaborParams gp, float3 cell, float3 cell_position)
ccl_device float3 gabor_cell_3d(GaborParams gp, float3 cell, float3 cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
float3 sum = zero_float3();
for (int i = 0; i < num_impulses; ++i) {
float3 rand_position = mix(
zero_float3(),
hash_float4_to_float3(make_float4(cell.x, cell.y, cell.z, float(i * GABOR_SEED))),
hash_float4_to_float3(make_float4(cell.x, cell.y, cell.z, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
float3 kernel_position = (cell_position - rand_position);
@ -140,21 +140,21 @@ ccl_device float3 gabor_cell_3d(GaborParams gp, float3 cell, float3 cell_positio
if (dv <= 1.0f) {
float phi;
float3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, &phi);
float3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, &phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
return sum;
}
ccl_device float3 gabor_cell_2d(GaborParams gp, float3 cell, float3 cell_position)
ccl_device float3 gabor_cell_2d(GaborParams gp, float3 cell, float3 cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
float3 sum = zero_float3();
for (int i = 0; i < num_impulses; ++i) {
float3 rand_position = mix(
zero_float3(),
hash_float4_to_float3(make_float4(cell.x, cell.y, cell.z, float(i * GABOR_SEED))),
hash_float4_to_float3(make_float4(cell.x, cell.y, cell.z, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
rand_position.z = 0.0f;
@ -164,7 +164,7 @@ ccl_device float3 gabor_cell_2d(GaborParams gp, float3 cell, float3 cell_positio
if (dv <= 1.0f) {
float phi;
float3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, &phi);
float3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, &phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
@ -176,7 +176,7 @@ ccl_device float gabor_coord_wrap(float a, float b)
return (b != 0.0f) ? a - b * floorf(a / b) : 0.0f;
}
ccl_device float gabor_grid_3d(GaborParams gp, float3 p, float scale, int periodic)
ccl_device float gabor_grid_3d(GaborParams gp, float3 p, float scale, int periodic, int seed)
{
float3 coords = p * scale;
float3 position = floor(coords);
@ -202,7 +202,7 @@ ccl_device float gabor_grid_3d(GaborParams gp, float3 p, float scale, int period
cell.z = gabor_coord_wrap(cell.z, scale);
}
sum += gabor_cell_3d(gp, cell, cell_position);
sum += gabor_cell_3d(gp, cell, cell_position, seed);
}
}
}
@ -218,7 +218,7 @@ ccl_device float gabor_grid_3d(GaborParams gp, float3 p, float scale, int period
}
}
ccl_device float gabor_grid_2d(GaborParams gp, float3 p, float scale, int periodic)
ccl_device float gabor_grid_2d(GaborParams gp, float3 p, float scale, int periodic, int seed)
{
float3 coords = make_float3(p.x, p.y, 0.0f) * scale;
float3 position = floor(coords);
@ -242,7 +242,7 @@ ccl_device float gabor_grid_2d(GaborParams gp, float3 p, float scale, int period
cell.y = gabor_coord_wrap(cell.y, scale);
}
sum += gabor_cell_2d(gp, cell, cell_position);
sum += gabor_cell_2d(gp, cell, cell_position, seed);
CharlieJolly marked this conversation as resolved Outdated

Is there a need for this if clause? It makes the behavior different to the other noise nodes when scale is 0.0.

Is there a need for this if clause? It makes the behavior different to the other noise nodes when scale is 0.0.

Removed this clause.

Removed this clause.

Sorry I misremembered. if (gp.roughness == 0.0f || gp.scl_lacunarity == 0.0f) was actually correct, see: 39a40d6f84/intern/cycles/kernel/svm/voronoi.h (L892)

Could you please change it back?

Sorry I misremembered. `if (gp.roughness == 0.0f || gp.scl_lacunarity == 0.0f)` was actually correct, see: https://projects.blender.org/blender/blender/src/commit/39a40d6f84a658d07860aef60487660a34aa0d3b/intern/cycles/kernel/svm/voronoi.h#L892 Could you please change it back?

This differs between noise and voronoi, I'm not sure which one is actually preferable. If the input is driven then it may make sense to keep it as is so the transition from 0 to 1 is smoother. The gabor function just returns midlevel value when scale lacunarity is zero.

This differs between noise and voronoi, I'm not sure which one is actually preferable. If the input is driven then it may make sense to keep it as is so the transition from 0 to 1 is smoother. The gabor function just returns midlevel value when scale lacunarity is zero.

This differs between noise and voronoi, I'm not sure which one is actually preferable.
The behavior for both noise and voronoi are the same. This is because when scale lacunarity is 0.0 the coordinates of all octaves higher than the base octaves are also (0.0, 0.0, 0.0). Due to how Perlin noise works this then also results in a constant 0.0 output for all higher octaves, which means it doesn't matter if the higher octaves are being computed or not.
But actually I think your way of doing it is actually better as it makes the output continuous as a function of Lacunarity, so I think you should just keep it as is and I'll change Voronoi to also have the same behavior.

>This differs between noise and voronoi, I'm not sure which one is actually preferable. The behavior for both noise and voronoi are the same. This is because when scale lacunarity is 0.0 the coordinates of all octaves higher than the base octaves are also (0.0, 0.0, 0.0). Due to how Perlin noise works this then also results in a constant 0.0 output for all higher octaves, which means it doesn't matter if the higher octaves are being computed or not. But actually I think your way of doing it is actually better as it makes the output continuous as a function of Lacunarity, so I think you should just keep it as is and I'll change Voronoi to also have the same behavior.
}
}
@ -275,9 +275,9 @@ ccl_device float gabor_fractal_noise(FractalParams fp,
}
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float3 co = p + float(use_origin_offset * i * GABOR_SEED);
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * i * GABOR_SEED;
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
gp.frequency *= fp.fre_lacunarity;
gp.rotation -= fp.rot_lacunarity;
sum += t * amp;
CharlieJolly marked this conversation as resolved Outdated

Perhaps a little nitpicky but perhaps return sum * gp.bandwidth / maxamp; makes the intention a little clearer as division isn't commutative.

Perhaps a little nitpicky but perhaps `return sum * gp.bandwidth / maxamp;` makes the intention a little clearer as division isn't commutative.
@ -287,9 +287,9 @@ ccl_device float gabor_fractal_noise(FractalParams fp,
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float3 co = p + float(use_origin_offset * (n + 1) * GABOR_SEED);
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * (n + 1) * GABOR_SEED;
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
float sum2 = sum + t * amp;
return mix(sum, sum2, rmd) * gp.gain / maxamp;
}

View File

@ -81,12 +81,12 @@ struct FractalParams {
* It's useful to allow impulses less than 1 to create spotted textures which is why int(impulses)
* is not directly used. Above 1 this provides a linear increase in impulses as the input value
* increases. */
int impulses_per_cell(vec3 cell, float impulses)
int impulses_per_cell(vec3 cell, float impulses, int seed)
{
int n = int(impulses);
float rmd = impulses - floor(impulses);
if (rmd > 0.0) {
float t = hash_vec3_to_float(cell);
float t = hash_vec4_to_float(vec4(cell, float(seed - GABOR_SEED)));
return (t <= rmd) ? n + 1 : n;
CharlieJolly marked this conversation as resolved Outdated

Add a note specifying that for non phasor modes, the result is just a broadcast of a single value in a vec3.

Add a note specifying that for non phasor modes, the result is just a broadcast of a single value in a `vec3`.

Note added.

Note added.
}
return n;
@ -171,13 +171,14 @@ vec3 gabor_sample(GaborParams gp, vec3 cell, int seed, out float phi)
}
CharlieJolly marked this conversation as resolved Outdated

If this is simply only passed to gabor_sample, why not call it in gabor_sample directly?

If this is simply only passed to `gabor_sample`, why not call it in `gabor_sample` directly?
/* Generate noise based on the cell position and number of impulses. */
vec3 gabor_cell_3d(GaborParams gp, vec3 cell, vec3 cell_position)
vec3 gabor_cell_3d(GaborParams gp, vec3 cell, vec3 cell_position, int seed)
{
CharlieJolly marked this conversation as resolved Outdated

The same for the Gaussian componenet, just compute it in gabor_sample directly.

The same for the Gaussian componenet, just compute it in `gabor_sample` directly.

Added to gabor_kernel function

Added to `gabor_kernel` function
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
vec3 sum = vec3(0.0);
for (int i = 0; i < num_impulses; ++i) {
vec3 rand_position = mix(
vec3(0.0), hash_vec4_to_vec3(vec4(cell, float(i * GABOR_SEED))), gp.cell_randomness);
vec3 rand_position = mix(vec3(0.0),
hash_vec4_to_vec3(vec4(cell, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
vec3 kernel_position = (cell_position - rand_position);
CharlieJolly marked this conversation as resolved Outdated

Unnecessary separation between declaration and initialization, just do vec3 rand_position = mix(...).

Unnecessary separation between declaration and initialization, just do `vec3 rand_position = mix(...)`.
@ -185,7 +186,7 @@ vec3 gabor_cell_3d(GaborParams gp, vec3 cell, vec3 cell_position)
if (dv <= 1.0) {
float phi;
vec3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
vec3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
@ -194,13 +195,14 @@ vec3 gabor_cell_3d(GaborParams gp, vec3 cell, vec3 cell_position)
/* Generate noise based on the cell position and number of impulses. Z position is zeroed for 2D
* cell as the kernel is still processed in 3D. */
vec3 gabor_cell_2d(GaborParams gp, vec3 cell, vec3 cell_position)
vec3 gabor_cell_2d(GaborParams gp, vec3 cell, vec3 cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
vec3 sum = vec3(0.0);
for (int i = 0; i < num_impulses; ++i) {
vec3 rand_position = mix(
vec3(0.0), hash_vec4_to_vec3(vec4(cell, float(i * GABOR_SEED))), gp.cell_randomness);
vec3 rand_position = mix(vec3(0.0),
hash_vec4_to_vec3(vec4(cell, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
rand_position.z = 0.0;
vec3 kernel_position = (cell_position - rand_position);
@ -209,7 +211,7 @@ vec3 gabor_cell_2d(GaborParams gp, vec3 cell, vec3 cell_position)
if (dv <= 1.0) {
float phi;
vec3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
vec3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
@ -223,7 +225,7 @@ float gabor_coord_wrap(float s, float p)
}
/* Calculate 3D noise using 3x3x3 cell grid. */
float gabor_grid_3d(GaborParams gp, vec3 p, float scale, int periodic)
float gabor_grid_3d(GaborParams gp, vec3 p, float scale, int periodic, int seed)
{
vec3 coords = p * scale;
vec3 position = floor(coords);
@ -250,7 +252,7 @@ float gabor_grid_3d(GaborParams gp, vec3 p, float scale, int periodic)
cell.z = gabor_coord_wrap(cell.z, scale);
}
sum += gabor_cell_3d(gp, cell, cell_position);
sum += gabor_cell_3d(gp, cell, cell_position, seed);
}
}
}
@ -268,7 +270,7 @@ float gabor_grid_3d(GaborParams gp, vec3 p, float scale, int periodic)
}
/* Calculate 2D noise using 3x3x1 cell grid. Less computational than 3x3x3 grid. */
float gabor_grid_2d(GaborParams gp, vec3 p, float scale, int periodic)
float gabor_grid_2d(GaborParams gp, vec3 p, float scale, int periodic, int seed)
{
vec3 coords = vec3(p.xy, 0.0) * scale;
vec3 position = floor(coords);
@ -293,7 +295,7 @@ float gabor_grid_2d(GaborParams gp, vec3 p, float scale, int periodic)
cell.y = gabor_coord_wrap(cell.y, scale);
}
sum += gabor_cell_2d(gp, cell, cell_position);
sum += gabor_cell_2d(gp, cell, cell_position, seed);
}
}
@ -364,9 +366,9 @@ float gabor_fractal_noise(FractalParams fp,
}
int n = int(octaves);
for (int i = 0; i <= n; i++) {
vec3 co = p + float(use_origin_offset * i * GABOR_SEED);
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * i * GABOR_SEED;
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
gp.frequency *= fp.fre_lacunarity;
gp.rotation -= fp.rot_lacunarity;
sum += t * amp;
@ -376,9 +378,9 @@ float gabor_fractal_noise(FractalParams fp,
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
vec3 co = p + float(use_origin_offset * (n + 1) * GABOR_SEED);
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * (n + 1) * GABOR_SEED;
float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
float sum2 = sum + t * amp;
return mix(sum, sum2, rmd) * gp.gain / maxamp;
}

View File

@ -213,12 +213,12 @@ typedef struct FractalParams {
float rot_lacunarity;
} FractalParams;
int impulses_per_cell(const float3 cell, const float impulses)
int impulses_per_cell(const float3 cell, const float impulses, const int seed)
{
const int n = int(impulses);
const float rmd = impulses - math::floor(impulses);
if (rmd > 0.0f) {
const float t = noise::hash_float_to_float(cell);
const float t = noise::hash_float_to_float(float4(cell, float(seed - GABOR_SEED)));
return (t <= rmd) ? n + 1 : n;
}
return n;
@ -299,14 +299,14 @@ static float3 gabor_sample(const GaborParams gp, const float3 cell, const int se
}
/* Generate noise based on the cell position. */
static float3 gabor_cell_3d(GaborParams &gp, float3 cell, float3 cell_position)
static float3 gabor_cell_3d(GaborParams &gp, float3 cell, float3 cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
float3 sum = float3(0.0f);
for (int i = 0; i < num_impulses; ++i) {
float3 rand_position = math::interpolate(
float3(0.0f),
noise::hash_float_to_float3(float4(cell, float(i * GABOR_SEED))),
noise::hash_float_to_float3(float4(cell, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
const float3 kernel_position = (cell_position - rand_position);
@ -315,21 +315,21 @@ static float3 gabor_cell_3d(GaborParams &gp, float3 cell, float3 cell_position)
if (dv <= 1.0f) {
float phi;
float3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
float3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
return sum;
}
static float3 gabor_cell_2d(GaborParams &gp, float3 cell, float3 cell_position)
static float3 gabor_cell_2d(GaborParams &gp, float3 cell, float3 cell_position, int seed)
{
int num_impulses = impulses_per_cell(cell, gp.impulses);
int num_impulses = impulses_per_cell(cell, gp.impulses, seed);
float3 sum = float3(0.0f);
for (int i = 0; i < num_impulses; ++i) {
float3 rand_position = math::interpolate(
float3(0.0f),
noise::hash_float_to_float3(float4(cell, float(i * GABOR_SEED))),
noise::hash_float_to_float3(float4(cell, float(seed + i * GABOR_SEED))),
gp.cell_randomness);
rand_position.z = 0.0f;
@ -339,7 +339,7 @@ static float3 gabor_cell_2d(GaborParams &gp, float3 cell, float3 cell_position)
if (dv <= 1.0f) {
float phi;
float3 omega = gabor_sample(gp, cell, (num_impulses + i) * GABOR_SEED, phi);
float3 omega = gabor_sample(gp, cell, seed + (num_impulses + i) * GABOR_SEED, phi);
sum += gabor_kernel(gp, omega, phi, kernel_position, dv);
}
}
@ -353,7 +353,8 @@ static float gabor_coord_wrap(const float a, const float b)
}
/* 3*3 cell grid */
static float gabor_grid_3d(GaborParams &gp, const float3 p, const float scale, const int periodic)
static float gabor_grid_3d(
GaborParams &gp, const float3 p, const float scale, const int periodic, const int seed)
{
const float3 coords = p * scale;
const float3 position = math::floor(coords);
@ -380,7 +381,7 @@ static float gabor_grid_3d(GaborParams &gp, const float3 p, const float scale, c
cell[2] = gabor_coord_wrap(cell[2], scale);
}
sum += gabor_cell_3d(gp, cell, cell_position);
sum += gabor_cell_3d(gp, cell, cell_position, seed);
}
}
}
@ -397,7 +398,8 @@ static float gabor_grid_3d(GaborParams &gp, const float3 p, const float scale, c
}
/* 2*2 cell grid */
static float gabor_grid_2d(GaborParams &gp, const float3 p, const float scale, const int periodic)
static float gabor_grid_2d(
GaborParams &gp, const float3 p, const float scale, const int periodic, const int seed)
{
const float3 coords = float3(p.x, p.y, 0.0f) * scale;
const float3 position = math::floor(coords);
@ -422,7 +424,7 @@ static float gabor_grid_2d(GaborParams &gp, const float3 p, const float scale, c
cell[1] = gabor_coord_wrap(cell[1], scale);
}
sum += gabor_cell_2d(gp, cell, cell_position);
sum += gabor_cell_2d(gp, cell, cell_position, seed);
}
}
@ -456,9 +458,9 @@ static float gabor_fractal_noise(FractalParams fp,
}
const int n = int(octaves);
for (int i = 0; i <= n; i++) {
float3 co = p + float(use_origin_offset * i * GABOR_SEED);
const float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * i * GABOR_SEED;
const float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
gp.frequency *= fp.fre_lacunarity;
gp.rotation -= fp.rot_lacunarity;
sum += t * amp;
@ -468,9 +470,9 @@ static float gabor_fractal_noise(FractalParams fp,
}
float rmd = octaves - math::floor(octaves);
if (rmd != 0.0f) {
float3 co = p + float(use_origin_offset * (n + 1) * GABOR_SEED);
const float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * co, scale, periodic) :
gabor_grid_2d(gp, fscale * co, scale, periodic);
int seed = use_origin_offset * (n + 1) * GABOR_SEED;
const float t = (dimensions == 3) ? gabor_grid_3d(gp, fscale * p, scale, periodic, seed) :
gabor_grid_2d(gp, fscale * p, scale, periodic, seed);
const float sum2 = sum + t * amp;
return ((1.0f - rmd) * sum + rmd * sum2) * gp.gain / maxamp;
}