Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorOmarSquircleArt <omar.squircleart@gmail.com>2019-09-04 18:54:32 +0300
committerOmarSquircleArt <omar.squircleart@gmail.com>2019-09-04 18:54:32 +0300
commit23564583a4988778b4c43496fd21818b286f6ba1 (patch)
tree3dc149c4e5c26ea2aac460ed582cb31def988470 /source
parent45d4c925799e94c6d442a9a9066af2d3305724e1 (diff)
Shading: Extend Noise node to other dimenstions.
This patch extends perlin noise to operate in 1D, 2D, 3D, and 4D space. The noise code has also been refactored to be more readable. The Color output and distortion patterns changed, so this patch breaks backward compatibility. This is due to the fact that we now use random offsets as noise seeds, as opposed to swizzling and constants offsets. Reviewers: brecht, JacquesLucke Differential Revision: https://developer.blender.org/D5560
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c22
-rw-r--r--source/blender/editors/space_node/drawnode.c8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl93
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl284
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl106
-rw-r--r--source/blender/makesdna/DNA_node_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c11
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_noise.c36
8 files changed, 501 insertions, 61 deletions
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index a3e9b8dc206..6a99ba2db58 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -756,6 +756,19 @@ static void update_vector_math_node_average_operator(bNodeTree *ntree)
}
}
+/* The Noise node now have a dimension property. This property should be
+ * initialized to 3 by default.
+ */
+static void update_noise_node_dimensions(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_TEX_NOISE) {
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ tex->dimensions = 3;
+ }
+ }
+}
+
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@@ -928,4 +941,13 @@ void do_versions_after_linking_cycles(Main *bmain)
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 4)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_noise_node_dimensions(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index b89f163f579..47433693e7b 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -948,6 +948,11 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
}
+static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "dimensions", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_tex_pointdensity(uiLayout *layout,
bContext *UNUSED(C),
PointerRNA *ptr)
@@ -1267,6 +1272,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_VORONOI:
ntype->draw_buttons = node_shader_buts_tex_voronoi;
break;
+ case SH_NODE_TEX_NOISE:
+ ntype->draw_buttons = node_shader_buts_tex_noise;
+ break;
case SH_NODE_TEX_POINTDENSITY:
ntype->draw_buttons = node_shader_buts_tex_pointdensity;
break;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
index 2a925c2a622..701b07b4aae 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
@@ -1,4 +1,89 @@
-float noise_turbulence(vec3 p, float octaves, int hard)
+/* The fractal_noise functions are all exactly the same except for the input type. */
+float fractal_noise(float p, float octaves)
+{
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ octaves = clamp(octaves, 0.0, 16.0);
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
+ float t = noise(fscale * p);
+ sum += t * amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
+ float rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ float t = noise(fscale * p);
+ float sum2 = sum + t * amp;
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ return (1.0 - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ return sum;
+ }
+}
+
+/* The fractal_noise functions are all exactly the same except for the input type. */
+float fractal_noise(vec2 p, float octaves)
+{
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ octaves = clamp(octaves, 0.0, 16.0);
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
+ float t = noise(fscale * p);
+ sum += t * amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
+ float rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ float t = noise(fscale * p);
+ float sum2 = sum + t * amp;
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ return (1.0 - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ return sum;
+ }
+}
+
+/* The fractal_noise functions are all exactly the same except for the input type. */
+float fractal_noise(vec3 p, float octaves)
+{
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ octaves = clamp(octaves, 0.0, 16.0);
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
+ float t = noise(fscale * p);
+ sum += t * amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
+ float rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ float t = noise(fscale * p);
+ float sum2 = sum + t * amp;
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ return (1.0 - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ return sum;
+ }
+}
+
+/* The fractal_noise functions are all exactly the same except for the input type. */
+float fractal_noise(vec4 p, float octaves)
{
float fscale = 1.0;
float amp = 1.0;
@@ -7,9 +92,6 @@ float noise_turbulence(vec3 p, float octaves, int hard)
int n = int(octaves);
for (int i = 0; i <= n; i++) {
float t = noise(fscale * p);
- if (hard != 0) {
- t = abs(2.0 * t - 1.0);
- }
sum += t * amp;
amp *= 0.5;
fscale *= 2.0;
@@ -17,9 +99,6 @@ float noise_turbulence(vec3 p, float octaves, int hard)
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
float t = noise(fscale * p);
- if (hard != 0) {
- t = abs(2.0 * t - 1.0);
- }
float sum2 = sum + t * amp;
sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl
index 8c6a10e3fe7..c184c61c269 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl
@@ -1,16 +1,106 @@
-float noise_fade(float t)
+/* Bilinear Interpolation:
+ *
+ * v2 v3
+ * @ + + + + @ y
+ * + + ^
+ * + + |
+ * + + |
+ * @ + + + + @ @------> x
+ * v0 v1
+ *
+ */
+float bi_mix(float v0, float v1, float v2, float v3, float x, float y)
+{
+ float x1 = 1.0 - x;
+ return (1.0 - y) * (v0 * x1 + v1 * x) + y * (v2 * x1 + v3 * x);
+}
+
+/* Trilinear Interpolation:
+ *
+ * v6 v7
+ * @ + + + + + + @
+ * +\ +\
+ * + \ + \
+ * + \ + \
+ * + \ v4 + \ v5
+ * + @ + + + +++ + @ z
+ * + + + + y ^
+ * v2 @ + +++ + + + @ v3 + \ |
+ * \ + \ + \ |
+ * \ + \ + \|
+ * \ + \ + +---------> x
+ * \+ \+
+ * @ + + + + + + @
+ * v0 v1
+ */
+float tri_mix(float v0,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6,
+ float v7,
+ float x,
+ float y,
+ float z)
+{
+ float x1 = 1.0 - x;
+ float y1 = 1.0 - y;
+ float z1 = 1.0 - z;
+ return z1 * (y1 * (v0 * x1 + v1 * x) + y * (v2 * x1 + v3 * x)) +
+ z * (y1 * (v4 * x1 + v5 * x) + y * (v6 * x1 + v7 * x));
+}
+
+float quad_mix(float v0,
+ float v1,
+ float v2,
+ float v3,
+ float v4,
+ float v5,
+ float v6,
+ float v7,
+ float v8,
+ float v9,
+ float v10,
+ float v11,
+ float v12,
+ float v13,
+ float v14,
+ float v15,
+ float x,
+ float y,
+ float z,
+ float w)
+{
+ return mix(tri_mix(v0, v1, v2, v3, v4, v5, v6, v7, x, y, z),
+ tri_mix(v8, v9, v10, v11, v12, v13, v14, v15, x, y, z),
+ w);
+}
+
+float fade(float t)
{
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
}
-float noise_scale3(float result)
+float negate_if(float value, uint condition)
{
- return 0.9820 * result;
+ return (condition != 0u) ? -value : value;
}
-float noise_nerp(float t, float a, float b)
+float noise_grad(uint hash, float x)
{
- return (1.0 - t) * a + t * b;
+ uint h = hash & 15u;
+ float g = 1u + (h & 7u);
+ return negate_if(g, h & 8u) * x;
+}
+
+float noise_grad(uint hash, float x, float y)
+{
+ uint h = hash & 7u;
+ float u = h < 4u ? x : y;
+ float v = 2.0 * (h < 4u ? y : x);
+ return negate_if(u, h & 1u) + negate_if(v, h & 2u);
}
float noise_grad(uint hash, float x, float y, float z)
@@ -19,56 +109,186 @@ float noise_grad(uint hash, float x, float y, float z)
float u = h < 8u ? x : y;
float vt = ((h == 12u) || (h == 14u)) ? x : z;
float v = h < 4u ? y : vt;
- return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v);
+ return negate_if(u, h & 1u) + negate_if(v, h & 2u);
+}
+
+float noise_grad(uint hash, float x, float y, float z, float w)
+{
+ uint h = hash & 31u;
+ float u = h < 24u ? x : y;
+ float v = h < 16u ? y : z;
+ float s = h < 8u ? z : w;
+ return negate_if(u, h & 1u) + negate_if(v, h & 2u) + negate_if(s, h & 4u);
}
-float noise_perlin(float x, float y, float z)
+float noise_perlin(float x)
{
int X;
float fx = floorfrac(x, X);
+ float u = fade(fx);
+
+ float r = mix(noise_grad(hash_int(X), fx), noise_grad(hash_int(X + 1), fx - 1.0), u);
+
+ return r;
+}
+
+float noise_perlin(vec2 vec)
+{
+ int X;
+ int Y;
+
+ float fx = floorfrac(vec.x, X);
+ float fy = floorfrac(vec.y, Y);
+
+ float u = fade(fx);
+ float v = fade(fy);
+
+ float r = bi_mix(noise_grad(hash_int2(X, Y), fx, fy),
+ noise_grad(hash_int2(X + 1, Y), fx - 1.0, fy),
+ noise_grad(hash_int2(X, Y + 1), fx, fy - 1.0),
+ noise_grad(hash_int2(X + 1, Y + 1), fx - 1.0, fy - 1.0),
+ u,
+ v);
+
+ return r;
+}
+
+float noise_perlin(vec3 vec)
+{
+ int X;
int Y;
- float fy = floorfrac(y, Y);
int Z;
- float fz = floorfrac(z, Z);
- float u = noise_fade(fx);
- float v = noise_fade(fy);
- float w = noise_fade(fz);
+ float fx = floorfrac(vec.x, X);
+ float fy = floorfrac(vec.y, Y);
+ float fz = floorfrac(vec.z, Z);
+
+ float u = fade(fx);
+ float v = fade(fy);
+ float w = fade(fz);
- float noise_u[2], noise_v[2];
+ float r = tri_mix(noise_grad(hash_int3(X, Y, Z), fx, fy, fz),
+ noise_grad(hash_int3(X + 1, Y, Z), fx - 1, fy, fz),
+ noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1, fz),
+ noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1, fy - 1, fz),
+ noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1),
+ noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1, fy, fz - 1),
+ noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1, fz - 1),
+ noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1, fy - 1, fz - 1),
+ u,
+ v,
+ w);
- noise_u[0] = noise_nerp(u,
- noise_grad(hash_int3(X, Y, Z), fx, fy, fz),
- noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz));
+ return r;
+}
- noise_u[1] = noise_nerp(u,
- noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz),
- noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
+float noise_perlin(vec4 vec)
+{
+ int X;
+ int Y;
+ int Z;
+ int W;
- noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]);
+ float fx = floorfrac(vec.x, X);
+ float fy = floorfrac(vec.y, Y);
+ float fz = floorfrac(vec.z, Z);
+ float fw = floorfrac(vec.w, W);
- noise_u[0] = noise_nerp(u,
- noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0),
- noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
+ float u = fade(fx);
+ float v = fade(fy);
+ float t = fade(fz);
+ float s = fade(fw);
- noise_u[1] = noise_nerp(
+ float r = quad_mix(
+ noise_grad(hash_int4(X, Y, Z, W), fx, fy, fz, fw),
+ noise_grad(hash_int4(X + 1, Y, Z, W), fx - 1.0, fy, fz, fw),
+ noise_grad(hash_int4(X, Y + 1, Z, W), fx, fy - 1.0, fz, fw),
+ noise_grad(hash_int4(X + 1, Y + 1, Z, W), fx - 1.0, fy - 1.0, fz, fw),
+ noise_grad(hash_int4(X, Y, Z + 1, W), fx, fy, fz - 1.0, fw),
+ noise_grad(hash_int4(X + 1, Y, Z + 1, W), fx - 1.0, fy, fz - 1.0, fw),
+ noise_grad(hash_int4(X, Y + 1, Z + 1, W), fx, fy - 1.0, fz - 1.0, fw),
+ noise_grad(hash_int4(X + 1, Y + 1, Z + 1, W), fx - 1.0, fy - 1.0, fz - 1.0, fw),
+ noise_grad(hash_int4(X, Y, Z, W + 1), fx, fy, fz, fw - 1.0),
+ noise_grad(hash_int4(X + 1, Y, Z, W + 1), fx - 1.0, fy, fz, fw - 1.0),
+ noise_grad(hash_int4(X, Y + 1, Z, W + 1), fx, fy - 1.0, fz, fw - 1.0),
+ noise_grad(hash_int4(X + 1, Y + 1, Z, W + 1), fx - 1.0, fy - 1.0, fz, fw - 1.0),
+ noise_grad(hash_int4(X, Y, Z + 1, W + 1), fx, fy, fz - 1.0, fw - 1.0),
+ noise_grad(hash_int4(X + 1, Y, Z + 1, W + 1), fx - 1.0, fy, fz - 1.0, fw - 1.0),
+ noise_grad(hash_int4(X, Y + 1, Z + 1, W + 1), fx, fy - 1.0, fz - 1.0, fw - 1.0),
+ noise_grad(hash_int4(X + 1, Y + 1, Z + 1, W + 1), fx - 1.0, fy - 1.0, fz - 1.0, fw - 1.0),
u,
- noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
- noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
+ v,
+ t,
+ s);
- noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]);
+ return r;
+}
- float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1]));
+/* Remap the output of noise to a predictable range [-1, 1].
+ * The scale values were computed experimentally by the OSL developers.
+ */
+float noise_scale1(float result)
+{
+ return 0.2500 * result;
+}
- return (isinf(r)) ? 0.0 : r;
+float noise_scale2(float result)
+{
+ return 0.6616 * result;
}
-float noise(vec3 p)
+float noise_scale3(float result)
+{
+ return 0.9820 * result;
+}
+
+float noise_scale4(float result)
+{
+ return 0.8344 * result;
+}
+
+/* Safe Signed And Unsigned Noise */
+
+float snoise(float p)
+{
+ float r = noise_perlin(p);
+ return (isinf(r)) ? 0.0 : noise_scale1(r);
+}
+
+float noise(float p)
+{
+ return 0.5 * snoise(p) + 0.5;
+}
+
+float snoise(vec2 p)
{
- return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5;
+ float r = noise_perlin(p);
+ return (isinf(r)) ? 0.0 : noise_scale2(r);
+}
+
+float noise(vec2 p)
+{
+ return 0.5 * snoise(p) + 0.5;
}
float snoise(vec3 p)
{
- return noise_perlin(p.x, p.y, p.z);
+ float r = noise_perlin(p);
+ return (isinf(r)) ? 0.0 : noise_scale3(r);
+}
+
+float noise(vec3 p)
+{
+ return 0.5 * snoise(p) + 0.5;
+}
+
+float snoise(vec4 p)
+{
+ float r = noise_perlin(p);
+ return (isinf(r)) ? 0.0 : noise_scale4(r);
+}
+
+float noise(vec4 p)
+{
+ return 0.5 * snoise(p) + 0.5;
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
index 30e27da16e8..e56b4a1d135 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
@@ -1,19 +1,99 @@
-void node_tex_noise(
- vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
+/* The following offset functions generate random offsets to be added to texture
+ * coordinates to act as a seed since the noise functions don't have seed values.
+ * A seed value is needed for generating distortion textures and color outputs.
+ * The offset's components are in the range [100, 200], not too high to cause
+ * bad precision and not to small to be noticeable. We use float seed because
+ * OSL only support float hashes.
+ */
+
+float random_float_offset(float seed)
+{
+ return 100.0 + hash_float_to_float(seed) * 100.0;
+}
+
+vec2 random_vec2_offset(float seed)
+{
+ return vec2(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0);
+}
+
+vec3 random_vec3_offset(float seed)
+{
+ return vec3(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 2.0)) * 100.0);
+}
+
+vec4 random_vec4_offset(float seed)
+{
+ return vec4(100.0 + hash_vec2_to_float(vec2(seed, 0.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 1.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 2.0)) * 100.0,
+ 100.0 + hash_vec2_to_float(vec2(seed, 3.0)) * 100.0);
+}
+
+void node_noise_texture_1d(
+ vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+{
+ float p = w * scale;
+ if (distortion != 0.0) {
+ p += noise(p + random_float_offset(0.0)) * distortion;
+ }
+
+ value = fractal_noise(p, detail);
+ color = vec4(value,
+ fractal_noise(p + random_float_offset(1.0), detail),
+ fractal_noise(p + random_float_offset(2.0), detail),
+ 1.0);
+}
+
+void node_noise_texture_2d(
+ vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+{
+ vec2 p = co.xy * scale;
+ if (distortion != 0.0) {
+ p += vec2(noise(p + random_vec2_offset(0.0)) * distortion,
+ noise(p + random_vec2_offset(1.0)) * distortion);
+ }
+
+ value = fractal_noise(p, detail);
+ color = vec4(value,
+ fractal_noise(p + random_vec2_offset(2.0), detail),
+ fractal_noise(p + random_vec2_offset(3.0), detail),
+ 1.0);
+}
+
+void node_noise_texture_3d(
+ vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
{
vec3 p = co * scale;
- int hard = 0;
if (distortion != 0.0) {
- vec3 r, offset = vec3(13.5, 13.5, 13.5);
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
- p += r;
+ p += vec3(noise(p + random_vec3_offset(0.0)) * distortion,
+ noise(p + random_vec3_offset(1.0)) * distortion,
+ noise(p + random_vec3_offset(2.0)) * distortion);
+ }
+
+ value = fractal_noise(p, detail);
+ color = vec4(value,
+ fractal_noise(p + random_vec3_offset(3.0), detail),
+ fractal_noise(p + random_vec3_offset(4.0), detail),
+ 1.0);
+}
+
+void node_noise_texture_4d(
+ vec3 co, float w, float scale, float detail, float distortion, out float value, out vec4 color)
+{
+ vec4 p = vec4(co, w) * scale;
+ if (distortion != 0.0) {
+ p += vec4(noise(p + random_vec4_offset(0.0)) * distortion,
+ noise(p + random_vec4_offset(1.0)) * distortion,
+ noise(p + random_vec4_offset(2.0)) * distortion,
+ noise(p + random_vec4_offset(3.0)) * distortion);
}
- fac = noise_turbulence(p, detail, hard);
- color = vec4(fac,
- noise_turbulence(vec3(p.y, p.x, p.z), detail, hard),
- noise_turbulence(vec3(p.y, p.z, p.x), detail, hard),
- 1);
+ value = fractal_noise(p, detail);
+ color = vec4(value,
+ fractal_noise(p + random_vec4_offset(4.0), detail),
+ fractal_noise(p + random_vec4_offset(5.0), detail),
+ 1.0);
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index af66add01f3..0787f41b810 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -869,6 +869,8 @@ typedef struct NodeTexGradient {
typedef struct NodeTexNoise {
NodeTexBase base;
+ int dimensions;
+ char _pad[4];
} NodeTexNoise;
typedef struct NodeTexVoronoi {
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 0909aa42a4d..988533e0f0e 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4346,8 +4346,17 @@ static void def_sh_tex_gradient(StructRNA *srna)
static void def_sh_tex_noise(StructRNA *srna)
{
+ PropertyRNA *prop;
+
RNA_def_struct_sdna_from(srna, "NodeTexNoise", "storage");
def_sh_tex(srna);
+
+ prop = RNA_def_property(srna, "dimensions", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "dimensions");
+ RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
+ RNA_def_property_ui_text(
+ prop, "Dimensions", "The dimensions of the space to evaluate the noise in");
+ RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
}
static void def_sh_tex_checker(StructRNA *srna)
@@ -4516,7 +4525,7 @@ static void def_sh_tex_white_noise(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
RNA_def_property_ui_text(
- prop, "Dimensions", "The number of dimensions to evaluate the noise in");
+ prop, "Dimensions", "The dimensions of the space to evaluate the noise in");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
index 34c4b17f255..8c35591d112 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c
@@ -23,6 +23,7 @@
static bNodeSocketTemplate sh_node_tex_noise_in[] = {
{SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f},
{SOCK_FLOAT, 1, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
@@ -30,27 +31,27 @@ static bNodeSocketTemplate sh_node_tex_noise_in[] = {
};
static bNodeSocketTemplate sh_node_tex_noise_out[] = {
- {SOCK_RGBA,
+ {SOCK_FLOAT,
0,
- N_("Color"),
+ N_("Fac"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
- PROP_NONE,
+ PROP_FACTOR,
SOCK_NO_INTERNAL_LINK},
- {SOCK_FLOAT,
+ {SOCK_RGBA,
0,
- N_("Fac"),
+ N_("Color"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
- PROP_FACTOR,
+ PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{-1, 0, ""},
};
@@ -60,6 +61,7 @@ static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise");
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
+ tex->dimensions = 3;
node->storage = tex;
}
@@ -74,10 +76,27 @@ static int node_shader_gpu_tex_noise(GPUMaterial *mat,
in[0].link = GPU_attribute(CD_ORCO, "");
GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), in[0].link, &in[0].link);
}
-
node_shader_gpu_tex_mapping(mat, node, in, out);
- return GPU_stack_link(mat, node, "node_tex_noise", in, out);
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ static const char *names[] = {
+ "",
+ "node_noise_texture_1d",
+ "node_noise_texture_2d",
+ "node_noise_texture_3d",
+ "node_noise_texture_4d",
+ };
+ return GPU_stack_link(mat, node, names[tex->dimensions], in, out);
+}
+
+static void node_shader_update_tex_noise(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
+
+ NodeTexNoise *tex = (NodeTexNoise *)node->storage;
+ nodeSetSocketAvailability(sockVector, tex->dimensions != 1);
+ nodeSetSocketAvailability(sockW, tex->dimensions == 1 || tex->dimensions == 4);
}
/* node type definition */
@@ -91,6 +110,7 @@ void register_node_type_sh_tex_noise(void)
node_type_storage(
&ntype, "NodeTexNoise", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_noise);
+ node_type_update(&ntype, node_shader_update_tex_noise);
nodeRegisterType(&ntype);
}