Nodes: Add Lacunarity and Normalize inputs to Noise node

This PR adds the Lacunarity and Normalize inputs to the Noise node
similar to the Voronoi node.

The Lacunarity input controls the scale factor by which each
successive Perlin noise octave is scaled. Which was previously hard
coded to a factor of 2.

The Noise node normalizes its output to the [0, 1] range by default.
The Normalize option makes it possible for the user to disable that.
To keep the behavior consistent with past versions it is enabled by
default.

To make the aforementioned normalization control easer to implement,
the fractal noise code now accumulates signed noise and remaps the
final sum, as opposed to accumulating positive [0, 1] noise.

Pull Request: https://projects.blender.org/blender/blender/pulls/110839
This commit is contained in:
Hoshinova 2023-08-15 17:38:45 +02:00 committed by Omar Emara
parent 969de5135a
commit 0702c24a36
20 changed files with 447 additions and 247 deletions

View File

@ -930,6 +930,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexNoise b_noise_node(b_node);
NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>();
noise->set_dimensions(b_noise_node.noise_dimensions());
noise->set_use_normalize(b_noise_node.normalize());
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
get_tex_mapping(noise, b_texture_mapping);
node = noise;

View File

@ -72,7 +72,7 @@ float safe_snoise(vector4 p)
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(float p, float details, float roughness)
float fractal_noise(float p, float details, float roughness, float lacunarity, int use_normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -81,27 +81,26 @@ float fractal_noise(float p, float details, float roughness)
float octaves = clamp(details, 0.0, 15.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector2 p, float details, float roughness)
float fractal_noise(vector2 p, float details, float roughness, float lacunarity, int use_normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -110,27 +109,26 @@ float fractal_noise(vector2 p, float details, float roughness)
float octaves = clamp(details, 0.0, 15.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector3 p, float details, float roughness)
float fractal_noise(vector3 p, float details, float roughness, float lacunarity, int use_normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -139,27 +137,26 @@ float fractal_noise(vector3 p, float details, float roughness)
float octaves = clamp(details, 0.0, 15.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vector4 p, float details, float roughness)
float fractal_noise(vector4 p, float details, float roughness, float lacunarity, int use_normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -168,22 +165,21 @@ float fractal_noise(vector4 p, float details, float roughness)
float octaves = clamp(details, 0.0, 15.0);
int n = (int)octaves;
for (int i = 0; i <= n; i++) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = safe_noise(fscale * p);
float t = safe_snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return use_normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return use_normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}

View File

@ -43,22 +43,34 @@ vector4 random_vector4_offset(float seed)
100.0 + noise("hash", seed, 3.0) * 100.0);
}
float noise_texture(float co, float detail, float roughness, float distortion, output color Color)
float noise_texture(float co,
float detail,
float roughness,
float lacunarity,
float distortion,
int use_normalize,
output color Color)
{
float p = co;
if (distortion != 0.0) {
p += safe_snoise(p + random_float_offset(0.0)) * distortion;
}
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_float_offset(1.0), detail, roughness),
fractal_noise(p + random_float_offset(2.0), detail, roughness));
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
Color = color(
value,
fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, use_normalize),
fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, use_normalize));
return value;
}
float noise_texture(
vector2 co, float detail, float roughness, float distortion, output color Color)
float noise_texture(vector2 co,
float detail,
float roughness,
float lacunarity,
float distortion,
int use_normalize,
output color Color)
{
vector2 p = co;
if (distortion != 0.0) {
@ -66,15 +78,21 @@ float noise_texture(
safe_snoise(p + random_vector2_offset(1.0)) * distortion);
}
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector2_offset(2.0), detail, roughness),
fractal_noise(p + random_vector2_offset(3.0), detail, roughness));
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
Color = color(
value,
fractal_noise(p + random_vector2_offset(2.0), detail, roughness, lacunarity, use_normalize),
fractal_noise(p + random_vector2_offset(3.0), detail, roughness, lacunarity, use_normalize));
return value;
}
float noise_texture(
vector3 co, float detail, float roughness, float distortion, output color Color)
float noise_texture(vector3 co,
float detail,
float roughness,
float lacunarity,
float distortion,
int use_normalize,
output color Color)
{
vector3 p = co;
if (distortion != 0.0) {
@ -83,15 +101,21 @@ float noise_texture(
safe_snoise(p + random_vector3_offset(2.0)) * distortion);
}
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector3_offset(3.0), detail, roughness),
fractal_noise(p + random_vector3_offset(4.0), detail, roughness));
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
Color = color(
value,
fractal_noise(p + random_vector3_offset(3.0), detail, roughness, lacunarity, use_normalize),
fractal_noise(p + random_vector3_offset(4.0), detail, roughness, lacunarity, use_normalize));
return value;
}
float noise_texture(
vector4 co, float detail, float roughness, float distortion, output color Color)
float noise_texture(vector4 co,
float detail,
float roughness,
float lacunarity,
float distortion,
int use_normalize,
output color Color)
{
vector4 p = co;
if (distortion != 0.0) {
@ -101,21 +125,24 @@ float noise_texture(
safe_snoise(p + random_vector4_offset(3.0)) * distortion);
}
float value = fractal_noise(p, detail, roughness);
Color = color(value,
fractal_noise(p + random_vector4_offset(4.0), detail, roughness),
fractal_noise(p + random_vector4_offset(5.0), detail, roughness));
float value = fractal_noise(p, detail, roughness, lacunarity, use_normalize);
Color = color(
value,
fractal_noise(p + random_vector4_offset(4.0), detail, roughness, lacunarity, use_normalize),
fractal_noise(p + random_vector4_offset(5.0), detail, roughness, lacunarity, use_normalize));
return value;
}
shader node_noise_texture(int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
string dimensions = "3D",
int use_normalize = 0,
vector3 Vector = vector3(0, 0, 0),
float W = 0.0,
float Scale = 5.0,
float Detail = 2.0,
float Roughness = 0.5,
float Lacunarity = 2.0,
float Distortion = 0.0,
output float Fac = 0.0,
output color Color = 0.0)
@ -128,13 +155,20 @@ shader node_noise_texture(int use_mapping = 0,
float w = W * Scale;
if (dimensions == "1D")
Fac = noise_texture(w, Detail, Roughness, Distortion, Color);
Fac = noise_texture(w, Detail, Roughness, Lacunarity, Distortion, use_normalize, Color);
else if (dimensions == "2D")
Fac = noise_texture(vector2(p[0], p[1]), Detail, Roughness, Distortion, Color);
Fac = noise_texture(
vector2(p[0], p[1]), Detail, Roughness, Lacunarity, Distortion, use_normalize, Color);
else if (dimensions == "3D")
Fac = noise_texture(p, Detail, Roughness, Distortion, Color);
Fac = noise_texture(p, Detail, Roughness, Lacunarity, Distortion, use_normalize, Color);
else if (dimensions == "4D")
Fac = noise_texture(vector4(p[0], p[1], p[2], w), Detail, Roughness, Distortion, Color);
Fac = noise_texture(vector4(p[0], p[1], p[2], w),
Detail,
Roughness,
Lacunarity,
Distortion,
use_normalize,
Color);
else
error("Unknown dimension!");
}

View File

@ -56,7 +56,7 @@ float wave(point p_input,
n += phase;
if (distortion != 0.0) {
n = n + (distortion * (fractal_noise(p * dscale, detail, droughness) * 2.0 - 1.0));
n = n + (distortion * (fractal_noise(p * dscale, detail, droughness, 2.0, 1) * 2.0 - 1.0));
}
if (profile == "sine") {

View File

@ -9,7 +9,8 @@
CCL_NAMESPACE_BEGIN
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_1d(float p, float octaves, float roughness)
ccl_device_noinline float fractal_noise_1d(
float p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
@ -18,27 +19,27 @@ ccl_device_noinline float fractal_noise_1d(float p, float octaves, float roughne
octaves = clamp(octaves, 0.0f, 15.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_1d(fscale * p);
float t = snoise_1d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
fscale *= lacunarity;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_1d(fscale * p);
float t = snoise_1d(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_2d(float2 p, float octaves, float roughness)
ccl_device_noinline float fractal_noise_2d(
float2 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
@ -47,27 +48,27 @@ ccl_device_noinline float fractal_noise_2d(float2 p, float octaves, float roughn
octaves = clamp(octaves, 0.0f, 15.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_2d(fscale * p);
float t = snoise_2d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
fscale *= lacunarity;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_2d(fscale * p);
float t = snoise_2d(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_3d(float3 p, float octaves, float roughness)
ccl_device_noinline float fractal_noise_3d(
float3 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
@ -76,27 +77,27 @@ ccl_device_noinline float fractal_noise_3d(float3 p, float octaves, float roughn
octaves = clamp(octaves, 0.0f, 15.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_3d(fscale * p);
float t = snoise_3d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
fscale *= lacunarity;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_3d(fscale * p);
float t = snoise_3d(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}
/* The fractal_noise_[1-4] functions are all exactly the same except for the input type. */
ccl_device_noinline float fractal_noise_4d(float4 p, float octaves, float roughness)
ccl_device_noinline float fractal_noise_4d(
float4 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
@ -105,22 +106,21 @@ ccl_device_noinline float fractal_noise_4d(float4 p, float octaves, float roughn
octaves = clamp(octaves, 0.0f, 15.0f);
int n = float_to_int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise_4d(fscale * p);
float t = snoise_4d(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
fscale *= lacunarity;
}
float rmd = octaves - floorf(octaves);
if (rmd != 0.0f) {
float t = noise_4d(fscale * p);
float t = snoise_4d(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
}

View File

@ -45,7 +45,9 @@ ccl_device_inline float4 random_float4_offset(float seed)
ccl_device void noise_texture_1d(float co,
float detail,
float roughness,
float lacunarity,
float distortion,
bool normalize,
bool color_is_needed,
ccl_private float *value,
ccl_private float3 *color)
@ -55,18 +57,21 @@ ccl_device void noise_texture_1d(float co,
p += snoise_1d(p + random_float_offset(0.0f)) * distortion;
}
*value = fractal_noise_1d(p, detail, roughness);
*value = fractal_noise_1d(p, detail, roughness, lacunarity, normalize);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_1d(p + random_float_offset(1.0f), detail, roughness),
fractal_noise_1d(p + random_float_offset(2.0f), detail, roughness));
*color = make_float3(
*value,
fractal_noise_1d(p + random_float_offset(1.0f), detail, roughness, lacunarity, normalize),
fractal_noise_1d(p + random_float_offset(2.0f), detail, roughness, lacunarity, normalize));
}
}
ccl_device void noise_texture_2d(float2 co,
float detail,
float roughness,
float lacunarity,
float distortion,
bool normalize,
bool color_is_needed,
ccl_private float *value,
ccl_private float3 *color)
@ -77,18 +82,22 @@ ccl_device void noise_texture_2d(float2 co,
snoise_2d(p + random_float2_offset(1.0f)) * distortion);
}
*value = fractal_noise_2d(p, detail, roughness);
*value = fractal_noise_2d(p, detail, roughness, lacunarity, normalize);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_2d(p + random_float2_offset(2.0f), detail, roughness),
fractal_noise_2d(p + random_float2_offset(3.0f), detail, roughness));
*color = make_float3(
*value,
fractal_noise_2d(p + random_float2_offset(2.0f), detail, roughness, lacunarity, normalize),
fractal_noise_2d(
p + random_float2_offset(3.0f), detail, roughness, lacunarity, normalize));
}
}
ccl_device void noise_texture_3d(float3 co,
float detail,
float roughness,
float lacunarity,
float distortion,
bool normalize,
bool color_is_needed,
ccl_private float *value,
ccl_private float3 *color)
@ -100,18 +109,22 @@ ccl_device void noise_texture_3d(float3 co,
snoise_3d(p + random_float3_offset(2.0f)) * distortion);
}
*value = fractal_noise_3d(p, detail, roughness);
*value = fractal_noise_3d(p, detail, roughness, lacunarity, normalize);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_3d(p + random_float3_offset(3.0f), detail, roughness),
fractal_noise_3d(p + random_float3_offset(4.0f), detail, roughness));
*color = make_float3(
*value,
fractal_noise_3d(p + random_float3_offset(3.0f), detail, roughness, lacunarity, normalize),
fractal_noise_3d(
p + random_float3_offset(4.0f), detail, roughness, lacunarity, normalize));
}
}
ccl_device void noise_texture_4d(float4 co,
float detail,
float roughness,
float lacunarity,
float distortion,
bool normalize,
bool color_is_needed,
ccl_private float *value,
ccl_private float3 *color)
@ -124,33 +137,37 @@ ccl_device void noise_texture_4d(float4 co,
snoise_4d(p + random_float4_offset(3.0f)) * distortion);
}
*value = fractal_noise_4d(p, detail, roughness);
*value = fractal_noise_4d(p, detail, roughness, lacunarity, normalize);
if (color_is_needed) {
*color = make_float3(*value,
fractal_noise_4d(p + random_float4_offset(4.0f), detail, roughness),
fractal_noise_4d(p + random_float4_offset(5.0f), detail, roughness));
*color = make_float3(
*value,
fractal_noise_4d(p + random_float4_offset(4.0f), detail, roughness, lacunarity, normalize),
fractal_noise_4d(
p + random_float4_offset(5.0f), detail, roughness, lacunarity, normalize));
}
}
ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *stack,
uint dimensions,
uint offsets1,
uint offsets2,
uint offsets3,
int offset)
{
uint vector_stack_offset, w_stack_offset, scale_stack_offset;
uint detail_stack_offset, roughness_stack_offset, distortion_stack_offset;
uint value_stack_offset, color_stack_offset;
uint vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset;
uint roughness_stack_offset, lacunarity_stack_offset, distortion_stack_offset,
value_stack_offset;
uint color_stack_offset, dimensions, normalize;
svm_unpack_node_uchar4(
offsets1, &vector_stack_offset, &w_stack_offset, &scale_stack_offset, &detail_stack_offset);
svm_unpack_node_uchar4(offsets2,
&roughness_stack_offset,
&lacunarity_stack_offset,
&distortion_stack_offset,
&value_stack_offset,
&color_stack_offset);
&value_stack_offset);
svm_unpack_node_uchar3(offsets3, &color_stack_offset, &dimensions, &normalize);
uint4 defaults1 = read_node(kg, &offset);
uint4 defaults2 = read_node(kg, &offset);
@ -160,7 +177,8 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
float scale = stack_load_float_default(stack, scale_stack_offset, defaults1.y);
float detail = stack_load_float_default(stack, detail_stack_offset, defaults1.z);
float roughness = stack_load_float_default(stack, roughness_stack_offset, defaults1.w);
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.x);
float lacunarity = stack_load_float_default(stack, lacunarity_stack_offset, defaults2.x);
float distortion = stack_load_float_default(stack, distortion_stack_offset, defaults2.y);
vector *= scale;
w *= scale;
@ -169,27 +187,45 @@ ccl_device_noinline int svm_node_tex_noise(KernelGlobals kg,
float3 color;
switch (dimensions) {
case 1:
noise_texture_1d(
w, detail, roughness, distortion, stack_valid(color_stack_offset), &value, &color);
noise_texture_1d(w,
detail,
roughness,
lacunarity,
distortion,
normalize,
stack_valid(color_stack_offset),
&value,
&color);
break;
case 2:
noise_texture_2d(make_float2(vector.x, vector.y),
detail,
roughness,
lacunarity,
distortion,
normalize,
stack_valid(color_stack_offset),
&value,
&color);
break;
case 3:
noise_texture_3d(
vector, detail, roughness, distortion, stack_valid(color_stack_offset), &value, &color);
noise_texture_3d(vector,
detail,
roughness,
lacunarity,
distortion,
normalize,
stack_valid(color_stack_offset),
&value,
&color);
break;
case 4:
noise_texture_4d(make_float4(vector.x, vector.y, vector.z, w),
detail,
roughness,
lacunarity,
distortion,
normalize,
stack_valid(color_stack_offset),
&value,
&color);

View File

@ -57,7 +57,7 @@ ccl_device_noinline_cpu float svm_wave(NodeWaveType type,
n += phase;
if (distortion != 0.0f)
n += distortion * (fractal_noise_3d(p * dscale, detail, droughness) * 2.0f - 1.0f);
n += distortion * (fractal_noise_3d(p * dscale, detail, droughness, 2.0f, true) * 2.0f - 1.0f);
if (profile == NODE_WAVE_PROFILE_SIN) {
return 0.5f + 0.5f * sinf(n - M_PI_2_F);

View File

@ -1120,11 +1120,14 @@ NODE_DEFINE(NoiseTextureNode)
dimensions_enum.insert("4D", 4);
SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
SOCKET_BOOLEAN(use_normalize, "Normalize", true);
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_TEXTURE_GENERATED);
SOCKET_IN_FLOAT(w, "W", 0.0f);
SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 2.0f);
SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
SOCKET_OUT_FLOAT(fac, "Fac");
@ -1142,6 +1145,7 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
ShaderInput *scale_in = input("Scale");
ShaderInput *detail_in = input("Detail");
ShaderInput *roughness_in = input("Roughness");
ShaderInput *lacunarity_in = input("Lacunarity");
ShaderInput *distortion_in = input("Distortion");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *color_out = output("Color");
@ -1151,22 +1155,28 @@ void NoiseTextureNode::compile(SVMCompiler &compiler)
int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
int detail_stack_offset = compiler.stack_assign_if_linked(detail_in);
int roughness_stack_offset = compiler.stack_assign_if_linked(roughness_in);
int lacunarity_stack_offset = compiler.stack_assign_if_linked(lacunarity_in);
int distortion_stack_offset = compiler.stack_assign_if_linked(distortion_in);
int fac_stack_offset = compiler.stack_assign_if_linked(fac_out);
int color_stack_offset = compiler.stack_assign_if_linked(color_out);
compiler.add_node(
NODE_TEX_NOISE,
dimensions,
compiler.encode_uchar4(
vector_stack_offset, w_stack_offset, scale_stack_offset, detail_stack_offset),
compiler.encode_uchar4(
roughness_stack_offset, distortion_stack_offset, fac_stack_offset, color_stack_offset));
compiler.encode_uchar4(roughness_stack_offset,
lacunarity_stack_offset,
distortion_stack_offset,
fac_stack_offset),
compiler.encode_uchar4(color_stack_offset, dimensions, use_normalize));
compiler.add_node(
__float_as_int(w), __float_as_int(scale), __float_as_int(detail), __float_as_int(roughness));
compiler.add_node(
__float_as_int(distortion), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
compiler.add_node(__float_as_int(lacunarity),
__float_as_int(distortion),
SVM_STACK_INVALID,
SVM_STACK_INVALID);
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
}
@ -1175,6 +1185,7 @@ void NoiseTextureNode::compile(OSLCompiler &compiler)
{
tex_mapping.compile(compiler);
compiler.parameter(this, "dimensions");
compiler.parameter(this, "use_normalize");
compiler.add(this, "node_noise_texture");
}

View File

@ -228,10 +228,12 @@ class NoiseTextureNode : public TextureNode {
SHADER_NODE_CLASS(NoiseTextureNode)
NODE_SOCKET_API(int, dimensions)
NODE_SOCKET_API(bool, use_normalize)
NODE_SOCKET_API(float, w)
NODE_SOCKET_API(float, scale)
NODE_SOCKET_API(float, detail)
NODE_SOCKET_API(float, roughness)
NODE_SOCKET_API(float, lacunarity)
NODE_SOCKET_API(float, distortion)
NODE_SOCKET_API(float3, vector)
};

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 15
#define BLENDER_FILE_SUBVERSION 16
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -74,36 +74,68 @@ float perlin(float4 position);
/* Fractal perlin noise in the range [0, 1]. */
float perlin_fractal(float position, float octaves, float roughness);
float perlin_fractal(float2 position, float octaves, float roughness);
float perlin_fractal(float3 position, float octaves, float roughness);
float perlin_fractal(float4 position, float octaves, float roughness);
float perlin_fractal(
float position, float octaves, float roughness, float lacunarity, bool normalize);
float perlin_fractal(
float2 position, float octaves, float roughness, float lacunarity, bool normalize);
float perlin_fractal(
float3 position, float octaves, float roughness, float lacunarity, bool normalize);
float perlin_fractal(
float4 position, float octaves, float roughness, float lacunarity, bool normalize);
/* Positive distorted fractal perlin noise. */
float perlin_fractal_distorted(float position, float octaves, float roughness, float distortion);
float perlin_fractal_distorted(float2 position, float octaves, float roughness, float distortion);
float perlin_fractal_distorted(float3 position, float octaves, float roughness, float distortion);
float perlin_fractal_distorted(float4 position, float octaves, float roughness, float distortion);
float perlin_fractal_distorted(float position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize);
float perlin_fractal_distorted(float2 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize);
float perlin_fractal_distorted(float3 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize);
float perlin_fractal_distorted(float4 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize);
/* Positive distorted fractal perlin noise that outputs a float3. */
float3 perlin_float3_fractal_distorted(float position,
float octaves,
float roughness,
float distortion);
float lacunarity,
float distortion,
bool normalize);
float3 perlin_float3_fractal_distorted(float2 position,
float octaves,
float roughness,
float distortion);
float lacunarity,
float distortion,
bool normalize);
float3 perlin_float3_fractal_distorted(float3 position,
float octaves,
float roughness,
float distortion);
float lacunarity,
float distortion,
bool normalize);
float3 perlin_float3_fractal_distorted(float4 position,
float octaves,
float roughness,
float distortion);
float lacunarity,
float distortion,
bool normalize);
/** \} */

View File

@ -531,7 +531,9 @@ float perlin(float4 position)
/* Positive fractal perlin noise. */
template<typename T> float perlin_fractal_template(T position, float octaves, float roughness)
template<typename T>
float perlin_fractal_template(
T position, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0f;
float amp = 1.0f;
@ -540,42 +542,46 @@ template<typename T> float perlin_fractal_template(T position, float octaves, fl
octaves = CLAMPIS(octaves, 0.0f, 15.0f);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = perlin(fscale * position);
float t = perlin_signed(fscale * position);
sum += t * amp;
maxamp += amp;
amp *= CLAMPIS(roughness, 0.0f, 1.0f);
fscale *= 2.0f;
fscale *= lacunarity;
}
float rmd = octaves - std::floor(octaves);
if (rmd == 0.0f) {
return sum / maxamp;
if (rmd != 0.0f) {
float t = perlin_signed(fscale * position);
float sum2 = sum + t * amp;
return normalize ? mix(0.5f * sum / maxamp + 0.5f, 0.5f * sum2 / (maxamp + amp) + 0.5f, rmd) :
mix(sum, sum2, rmd);
}
else {
return normalize ? 0.5f * sum / maxamp + 0.5f : sum;
}
float t = perlin(fscale * position);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0f - rmd) * sum + rmd * sum2;
}
float perlin_fractal(float position, float octaves, float roughness)
float perlin_fractal(
float position, float octaves, float roughness, float lacunarity, bool normalize)
{
return perlin_fractal_template(position, octaves, roughness);
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal(float2 position, float octaves, float roughness)
float perlin_fractal(
float2 position, float octaves, float roughness, float lacunarity, bool normalize)
{
return perlin_fractal_template(position, octaves, roughness);
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal(float3 position, float octaves, float roughness)
float perlin_fractal(
float3 position, float octaves, float roughness, float lacunarity, bool normalize)
{
return perlin_fractal_template(position, octaves, roughness);
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal(float4 position, float octaves, float roughness)
float perlin_fractal(
float4 position, float octaves, float roughness, float lacunarity, bool normalize)
{
return perlin_fractal_template(position, octaves, roughness);
return perlin_fractal_template(position, octaves, roughness, lacunarity, normalize);
}
/* The following offset functions generate random offsets to be added to
@ -641,28 +647,48 @@ BLI_INLINE float4 perlin_distortion(float4 position, float strength)
/* Positive distorted fractal perlin noise. */
float perlin_fractal_distorted(float position, float octaves, float roughness, float distortion)
float perlin_fractal_distorted(float position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return perlin_fractal(position, octaves, roughness);
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal_distorted(float2 position, float octaves, float roughness, float distortion)
float perlin_fractal_distorted(float2 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return perlin_fractal(position, octaves, roughness);
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal_distorted(float3 position, float octaves, float roughness, float distortion)
float perlin_fractal_distorted(float3 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return perlin_fractal(position, octaves, roughness);
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
}
float perlin_fractal_distorted(float4 position, float octaves, float roughness, float distortion)
float perlin_fractal_distorted(float4 position,
float octaves,
float roughness,
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return perlin_fractal(position, octaves, roughness);
return perlin_fractal(position, octaves, roughness, lacunarity, normalize);
}
/* Positive distorted fractal perlin noise that outputs a float3. The arbitrary seeds are for
@ -671,45 +697,65 @@ float perlin_fractal_distorted(float4 position, float octaves, float roughness,
float3 perlin_float3_fractal_distorted(float position,
float octaves,
float roughness,
float distortion)
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return float3(perlin_fractal(position, octaves, roughness),
perlin_fractal(position + random_float_offset(1.0f), octaves, roughness),
perlin_fractal(position + random_float_offset(2.0f), octaves, roughness));
return float3(
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float_offset(1.0f), octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float_offset(2.0f), octaves, roughness, lacunarity, normalize));
}
float3 perlin_float3_fractal_distorted(float2 position,
float octaves,
float roughness,
float distortion)
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return float3(perlin_fractal(position, octaves, roughness),
perlin_fractal(position + random_float2_offset(2.0f), octaves, roughness),
perlin_fractal(position + random_float2_offset(3.0f), octaves, roughness));
return float3(
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float2_offset(2.0f), octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float2_offset(3.0f), octaves, roughness, lacunarity, normalize));
}
float3 perlin_float3_fractal_distorted(float3 position,
float octaves,
float roughness,
float distortion)
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return float3(perlin_fractal(position, octaves, roughness),
perlin_fractal(position + random_float3_offset(3.0f), octaves, roughness),
perlin_fractal(position + random_float3_offset(4.0f), octaves, roughness));
return float3(
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float3_offset(3.0f), octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float3_offset(4.0f), octaves, roughness, lacunarity, normalize));
}
float3 perlin_float3_fractal_distorted(float4 position,
float octaves,
float roughness,
float distortion)
float lacunarity,
float distortion,
bool normalize)
{
position += perlin_distortion(position, distortion);
return float3(perlin_fractal(position, octaves, roughness),
perlin_fractal(position + random_float4_offset(4.0f), octaves, roughness),
perlin_fractal(position + random_float4_offset(5.0f), octaves, roughness));
return float3(
perlin_fractal(position, octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float4_offset(4.0f), octaves, roughness, lacunarity, normalize),
perlin_fractal(
position + random_float4_offset(5.0f), octaves, roughness, lacunarity, normalize));
}
/** \} */

View File

@ -636,6 +636,20 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 16)) {
/* Set Normalize property of Noise Texture node to true. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type != NTREE_CUSTOM) {
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == SH_NODE_TEX_NOISE) {
((NodeTexNoise *)node->storage)->normalize = true;
}
}
}
}
FOREACH_NODETREE_END;
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -2,7 +2,7 @@
#pragma BLENDER_REQUIRE(gpu_shader_material_noise.glsl)
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(float p, float octaves, float roughness)
float fractal_noise(float p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -11,27 +11,26 @@ float fractal_noise(float p, float octaves, float roughness)
octaves = clamp(octaves, 0.0, 15.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec2 p, float octaves, float roughness)
float fractal_noise(vec2 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -40,27 +39,26 @@ float fractal_noise(vec2 p, float octaves, float roughness)
octaves = clamp(octaves, 0.0, 15.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec3 p, float octaves, float roughness)
float fractal_noise(vec3 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -69,27 +67,26 @@ float fractal_noise(vec3 p, float octaves, float roughness)
octaves = clamp(octaves, 0.0, 15.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}
/* The fractal_noise functions are all exactly the same except for the input type. */
float fractal_noise(vec4 p, float octaves, float roughness)
float fractal_noise(vec4 p, float octaves, float roughness, float lacunarity, bool normalize)
{
float fscale = 1.0;
float amp = 1.0;
@ -98,21 +95,20 @@ float fractal_noise(vec4 p, float octaves, float roughness)
octaves = clamp(octaves, 0.0, 15.0);
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
sum += t * amp;
maxamp += amp;
amp *= clamp(roughness, 0.0, 1.0);
fscale *= 2.0;
fscale *= lacunarity;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
float t = snoise(fscale * p);
float sum2 = sum + t * amp;
sum /= maxamp;
sum2 /= maxamp + amp;
return (1.0 - rmd) * sum + rmd * sum2;
return normalize ? mix(0.5 * sum / maxamp + 0.5, 0.5 * sum2 / (maxamp + amp) + 0.5, rmd) :
mix(sum, sum2, rmd);
}
else {
return sum / maxamp;
return normalize ? 0.5 * sum / maxamp + 0.5 : sum;
}
}

View File

@ -41,7 +41,9 @@ void node_noise_texture_1d(vec3 co,
float scale,
float detail,
float roughness,
float lacunarity,
float distortion,
float normalize,
out float value,
out vec4 color)
{
@ -50,11 +52,12 @@ void node_noise_texture_1d(vec3 co,
p += snoise(p + random_float_offset(0.0)) * distortion;
}
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_float_offset(1.0), detail, roughness),
fractal_noise(p + random_float_offset(2.0), detail, roughness),
1.0);
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
color = vec4(
value,
fractal_noise(p + random_float_offset(1.0), detail, roughness, lacunarity, normalize != 0.0),
fractal_noise(p + random_float_offset(2.0), detail, roughness, lacunarity, normalize != 0.0),
1.0);
}
void node_noise_texture_2d(vec3 co,
@ -62,7 +65,9 @@ void node_noise_texture_2d(vec3 co,
float scale,
float detail,
float roughness,
float lacunarity,
float distortion,
float normalize,
out float value,
out vec4 color)
{
@ -72,11 +77,12 @@ void node_noise_texture_2d(vec3 co,
snoise(p + random_vec2_offset(1.0)) * distortion);
}
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec2_offset(2.0), detail, roughness),
fractal_noise(p + random_vec2_offset(3.0), detail, roughness),
1.0);
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
color = vec4(
value,
fractal_noise(p + random_vec2_offset(2.0), detail, roughness, lacunarity, normalize != 0.0),
fractal_noise(p + random_vec2_offset(3.0), detail, roughness, lacunarity, normalize != 0.0),
1.0);
}
void node_noise_texture_3d(vec3 co,
@ -84,7 +90,9 @@ void node_noise_texture_3d(vec3 co,
float scale,
float detail,
float roughness,
float lacunarity,
float distortion,
float normalize,
out float value,
out vec4 color)
{
@ -95,11 +103,12 @@ void node_noise_texture_3d(vec3 co,
snoise(p + random_vec3_offset(2.0)) * distortion);
}
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec3_offset(3.0), detail, roughness),
fractal_noise(p + random_vec3_offset(4.0), detail, roughness),
1.0);
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
color = vec4(
value,
fractal_noise(p + random_vec3_offset(3.0), detail, roughness, lacunarity, normalize != 0.0),
fractal_noise(p + random_vec3_offset(4.0), detail, roughness, lacunarity, normalize != 0.0),
1.0);
}
void node_noise_texture_4d(vec3 co,
@ -107,7 +116,9 @@ void node_noise_texture_4d(vec3 co,
float scale,
float detail,
float roughness,
float lacunarity,
float distortion,
float normalize,
out float value,
out vec4 color)
{
@ -119,9 +130,10 @@ void node_noise_texture_4d(vec3 co,
snoise(p + random_vec4_offset(3.0)) * distortion);
}
value = fractal_noise(p, detail, roughness);
color = vec4(value,
fractal_noise(p + random_vec4_offset(4.0), detail, roughness),
fractal_noise(p + random_vec4_offset(5.0), detail, roughness),
1.0);
value = fractal_noise(p, detail, roughness, lacunarity, normalize != 0.0);
color = vec4(
value,
fractal_noise(p + random_vec4_offset(4.0), detail, roughness, lacunarity, normalize != 0.0),
fractal_noise(p + random_vec4_offset(5.0), detail, roughness, lacunarity, normalize != 0.0),
1.0);
}

View File

@ -51,7 +51,8 @@ float calc_wave(vec3 p,
n += phase;
if (distortion != 0.0) {
n += distortion * (fractal_noise(p * detail_scale, detail, detail_roughness) * 2.0 - 1.0);
n += distortion *
(fractal_noise(p * detail_scale, detail, detail_roughness, 2.0, true) * 2.0 - 1.0);
}
if (wave_profile == 0) { /* profile sin */

View File

@ -1215,7 +1215,8 @@ typedef struct NodeTexGradient {
typedef struct NodeTexNoise {
NodeTexBase base;
int dimensions;
char _pad[4];
uint8_t normalize;
char _pad[3];
} NodeTexNoise;
typedef struct NodeTexVoronoi {

View File

@ -5154,6 +5154,11 @@ static void def_sh_tex_noise(StructRNA *srna)
RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for");
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "normalize", 0);
RNA_def_property_ui_text(prop, "Normalize", "Normalize outputs to 0.0 to 1.0 range");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_sh_tex_checker(StructRNA *srna)

View File

@ -28,6 +28,11 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b)
.max(1.0f)
.default_value(0.5f)
.subtype(PROP_FACTOR);
b.add_input<decl::Float>("Lacunarity")
.min(0.0f)
.max(1000.0f)
.default_value(2.0f)
.description("The scale of a Perlin noise octave relative to that of the previous octave");
b.add_input<decl::Float>("Distortion").min(-1000.0f).max(1000.0f).default_value(0.0f);
b.add_output<decl::Float>("Fac").no_muted_links();
b.add_output<decl::Color>("Color").no_muted_links();
@ -36,6 +41,7 @@ static void sh_node_tex_noise_declare(NodeDeclarationBuilder &b)
static void node_shader_buts_tex_noise(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiItemR(layout, ptr, "noise_dimensions", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
uiItemR(layout, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
}
static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node)
@ -44,6 +50,7 @@ static void node_shader_init_tex_noise(bNodeTree * /*ntree*/, bNode *node)
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->dimensions = 3;
tex->normalize = true;
node->storage = tex;
}
@ -68,8 +75,10 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat,
node_shader_gpu_tex_mapping(mat, node, in, out);
const NodeTexNoise &storage = node_storage(*node);
float normalize = storage.normalize;
const char *name = gpu_shader_get_name(storage.dimensions);
return GPU_stack_link(mat, node, name, in, out);
return GPU_stack_link(mat, node, name, in, out, GPU_constant(&normalize));
}
static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
@ -85,9 +94,10 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
class NoiseFunction : public mf::MultiFunction {
private:
int dimensions_;
bool normalize_;
public:
NoiseFunction(int dimensions) : dimensions_(dimensions)
NoiseFunction(int dimensions, bool normalize) : dimensions_(dimensions), normalize_(normalize)
{
BLI_assert(dimensions >= 1 && dimensions <= 4);
static std::array<mf::Signature, 4> signatures{
@ -114,6 +124,7 @@ class NoiseFunction : public mf::MultiFunction {
builder.single_input<float>("Scale");
builder.single_input<float>("Detail");
builder.single_input<float>("Roughness");
builder.single_input<float>("Lacunarity");
builder.single_input<float>("Distortion");
builder.single_output<float>("Fac", mf::ParamFlag::SupportsUnusedOutput);
@ -128,6 +139,7 @@ class NoiseFunction : public mf::MultiFunction {
const VArray<float> &scale = params.readonly_single_input<float>(param++, "Scale");
const VArray<float> &detail = params.readonly_single_input<float>(param++, "Detail");
const VArray<float> &roughness = params.readonly_single_input<float>(param++, "Roughness");
const VArray<float> &lacunarity = params.readonly_single_input<float>(param++, "Lacunarity");
const VArray<float> &distortion = params.readonly_single_input<float>(param++, "Distortion");
MutableSpan<float> r_factor = params.uninitialized_single_output_if_required<float>(param++,
@ -145,14 +157,14 @@ class NoiseFunction : public mf::MultiFunction {
mask.foreach_index([&](const int64_t i) {
const float position = w[i] * scale[i];
r_factor[i] = noise::perlin_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
});
}
if (compute_color) {
mask.foreach_index([&](const int64_t i) {
const float position = w[i] * scale[i];
const float3 c = noise::perlin_float3_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
});
}
@ -164,14 +176,14 @@ class NoiseFunction : public mf::MultiFunction {
mask.foreach_index([&](const int64_t i) {
const float2 position = float2(vector[i] * scale[i]);
r_factor[i] = noise::perlin_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
});
}
if (compute_color) {
mask.foreach_index([&](const int64_t i) {
const float2 position = float2(vector[i] * scale[i]);
const float3 c = noise::perlin_float3_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
});
}
@ -183,14 +195,14 @@ class NoiseFunction : public mf::MultiFunction {
mask.foreach_index([&](const int64_t i) {
const float3 position = vector[i] * scale[i];
r_factor[i] = noise::perlin_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
});
}
if (compute_color) {
mask.foreach_index([&](const int64_t i) {
const float3 position = vector[i] * scale[i];
const float3 c = noise::perlin_float3_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
});
}
@ -206,7 +218,7 @@ class NoiseFunction : public mf::MultiFunction {
const float4 position{
position_vector[0], position_vector[1], position_vector[2], position_w};
r_factor[i] = noise::perlin_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
});
}
if (compute_color) {
@ -216,7 +228,7 @@ class NoiseFunction : public mf::MultiFunction {
const float4 position{
position_vector[0], position_vector[1], position_vector[2], position_w};
const float3 c = noise::perlin_float3_fractal_distorted(
position, detail[i], roughness[i], distortion[i]);
position, detail[i], roughness[i], lacunarity[i], distortion[i], normalize_);
r_color[i] = ColorGeometry4f(c[0], c[1], c[2], 1.0f);
});
}
@ -237,7 +249,7 @@ class NoiseFunction : public mf::MultiFunction {
static void sh_node_noise_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const NodeTexNoise &storage = node_storage(builder.node());
builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions);
builder.construct_and_set_matching_fn<NoiseFunction>(storage.dimensions, storage.normalize);
}
} // namespace blender::nodes::node_shader_tex_noise_cc

View File

@ -175,7 +175,8 @@ class WaveFunction : public mf::MultiFunction {
if (distortion[i] != 0.0f) {
n += distortion[i] *
(noise::perlin_fractal(p * dscale[i], detail[i], droughness[i]) * 2.0f - 1.0f);
(noise::perlin_fractal(p * dscale[i], detail[i], droughness[i], 2.0f, true) * 2.0f -
1.0f);
}
switch (wave_profile_) {