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
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/blender_shader.cpp2
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl122
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h57
-rw-r--r--intern/cycles/kernel/svm/svm_types.h15
-rw-r--r--intern/cycles/kernel/svm/svm_voronoi.h197
-rw-r--r--intern/cycles/render/nodes.cpp39
-rw-r--r--intern/cycles/render/nodes.h4
-rw-r--r--intern/cycles/util/util_math.h10
-rw-r--r--intern/cycles/util/util_math_float3.h17
-rw-r--r--intern/cycles/util/util_math_int3.h18
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl2
-rw-r--r--source/blender/makesdna/DNA_node_types.h19
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c46
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c21
15 files changed, 409 insertions, 162 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index e254ee6f68d..6129565fec5 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -747,6 +747,8 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
+ voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
+ voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
node = voronoi;
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 0c3b95ae4d0..2e47d74a414 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -17,12 +17,93 @@
#include "stdosl.h"
#include "node_texture.h"
+void voronoi_m(point p, string metric, float e, float da[4], point pa[4])
+{
+ /* Compute the distance to and the position of the four closest neighbors to p.
+ *
+ * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
+ * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
+ * contain the distance to the closest point and its coordinates respectively.
+ */
+ int xx, yy, zz, xi, yi, zi;
+
+ xi = (int)floor(p[0]);
+ yi = (int)floor(p[1]);
+ zi = (int)floor(p[2]);
+
+ da[0] = 1e10;
+ da[1] = 1e10;
+ da[2] = 1e10;
+ da[3] = 1e10;
+
+ for (xx = xi - 1; xx <= xi + 1; xx++) {
+ for (yy = yi - 1; yy <= yi + 1; yy++) {
+ for (zz = zi - 1; zz <= zi + 1; zz++) {
+ point ip = point(xx, yy, zz);
+ point vp = (point)cellnoise_color(ip);
+ point pd = p - (vp + ip);
+
+ float d = 0.0;
+ if (metric == "distance") {
+ d = dot(pd, pd);
+ }
+ else if (metric == "manhattan") {
+ d = fabs(pd[0]) + fabs(pd[1]) + fabs(pd[2]);
+ }
+ else if (metric == "chebychev") {
+ d = max(fabs(pd[0]), max(fabs(pd[1]), fabs(pd[2])));
+ }
+ else if (metric == "minkowski") {
+ d = pow(pow(fabs(pd[0]), e) + pow(fabs(pd[1]), e) + pow(fabs(pd[2]), e), 1.0/e);
+ }
+
+ vp += point(xx, yy, zz);
+
+ if (d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
+}
+
/* Voronoi */
shader node_voronoi_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 coloring = "intensity",
+ string metric = "distance",
+ string feature = "F1",
+ float Exponent = 1.0,
float Scale = 5.0,
point Vector = P,
output float Fac = 0.0,
@@ -37,17 +118,48 @@ shader node_voronoi_texture(
float da[4];
point pa[4];
- voronoi(p * Scale, 1.0, da, pa);
+ /* compute distance and point coordinate of 4 nearest neighbours */
+ voronoi_m(p * Scale, metric, Exponent, da, pa);
- /* Colored output */
if (coloring == "intensity") {
- Fac = fabs(da[0]);
+ /* Intensity output */
+ if (feature == "F1") {
+ Fac = fabs(da[0]);
+ }
+ else if (feature == "F2") {
+ Fac = fabs(da[1]);
+ }
+ else if (feature == "F3") {
+ Fac = fabs(da[2]);
+ }
+ else if (feature == "F4") {
+ Fac = fabs(da[3]);
+ }
+ else if (feature == "F2F1") {
+ Fac = fabs(da[1] - da[0]);
+ }
Color = color(Fac);
}
else {
- Color = cellnoise_color(pa[0]);
- Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
+ /* Color output */
+ if (feature == "F1") {
+ Color = pa[0];
+ }
+ else if (feature == "F2") {
+ Color = pa[1];
+ }
+ else if (feature == "F3") {
+ Color = pa[2];
+ }
+ else if (feature == "F4") {
+ Color = pa[3];
+ }
+ else if (feature == "F2F1") {
+ Color = fabs(pa[1] - pa[0]);
+ }
+ Color = cellnoise_color(Color);
+ Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
}
}
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index 38074f0faff..8c425ecf326 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -32,12 +32,7 @@
CCL_NAMESPACE_BEGIN
-#ifndef __KERNEL_SSE2__
-ccl_device int quick_floor(float x)
-{
- return float_to_int(x) - ((x < 0) ? 1 : 0);
-}
-#else
+#ifdef __KERNEL_SSE2__
ccl_device_inline ssei quick_floor_sse(const ssef& x)
{
ssei b = truncatei(x);
@@ -46,18 +41,6 @@ ccl_device_inline ssei quick_floor_sse(const ssef& x)
}
#endif
-#ifndef __KERNEL_SSE2__
-ccl_device float bits_to_01(uint bits)
-{
- return bits * (1.0f/(float)0xFFFFFFFF);
-}
-#else
-ccl_device_inline ssef bits_to_01_sse(const ssei& bits)
-{
- return uint32_to_float(bits) * ssef(1.0f/(float)0xFFFFFFFF);
-}
-#endif
-
ccl_device uint hash(uint kx, uint ky, uint kz)
{
// define some handy macros
@@ -129,7 +112,7 @@ ccl_device uint phash(int kx, int ky, int kz, int3 p)
#ifndef __KERNEL_SSE2__
ccl_device float floorfrac(float x, int* i)
{
- *i = quick_floor(x);
+ *i = quick_floor_to_int(x);
return x - *i;
}
#else
@@ -304,33 +287,27 @@ ccl_device float snoise(float3 p)
}
/* cell noise */
-#ifndef __KERNEL_SSE2__
-ccl_device_noinline float cellnoise(float3 p)
+ccl_device float cellnoise(float3 p)
{
- uint ix = quick_floor(p.x);
- uint iy = quick_floor(p.y);
- uint iz = quick_floor(p.z);
-
- return bits_to_01(hash(ix, iy, iz));
+ int3 ip = quick_floor_to_int3(p);
+ return bits_to_01(hash(ip.x, ip.y, ip.z));
}
-ccl_device float3 cellnoise_color(float3 p)
+ccl_device float3 cellnoise3(float3 p)
{
- float r = cellnoise(p);
- float g = cellnoise(make_float3(p.y, p.x, p.z));
- float b = cellnoise(make_float3(p.y, p.z, p.x));
-
+ int3 ip = quick_floor_to_int3(p);
+#ifndef __KERNEL_SSE__
+ float r = bits_to_01(hash(ip.x, ip.y, ip.z));
+ float g = bits_to_01(hash(ip.y, ip.x, ip.z));
+ float b = bits_to_01(hash(ip.y, ip.z, ip.x));
return make_float3(r, g, b);
-}
#else
-ccl_device ssef cellnoise_color(const ssef& p)
-{
- ssei ip = quick_floor_sse(p);
- ssei ip_yxz = shuffle<1, 0, 2, 3>(ip);
- ssei ip_xyy = shuffle<0, 1, 1, 3>(ip);
- ssei ip_zzx = shuffle<2, 2, 0, 3>(ip);
- return bits_to_01_sse(hash_sse(ip_xyy, ip_yxz, ip_zzx));
-}
+ ssei ip_yxz = shuffle<1, 0, 2, 3>(ssei(ip.m128));
+ ssei ip_xyy = shuffle<0, 1, 1, 3>(ssei(ip.m128));
+ ssei ip_zzx = shuffle<2, 2, 0, 3>(ssei(ip.m128));
+ ssei bits = hash_sse(ip_xyy, ip_yxz, ip_zzx);
+ return float3(uint32_to_float(bits) * ssef(1.0f/(float)0xFFFFFFFF));
#endif
+}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 0fde5126434..e03ad3a0cfe 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -338,6 +338,21 @@ typedef enum NodeVoronoiColoring {
NODE_VORONOI_CELLS
} NodeVoronoiColoring;
+typedef enum NodeVoronoiDistanceMetric {
+ NODE_VORONOI_DISTANCE,
+ NODE_VORONOI_MANHATTAN,
+ NODE_VORONOI_CHEBYCHEV,
+ NODE_VORONOI_MINKOWSKI
+} NodeVoronoiDistanceMetric;
+
+typedef enum NodeVoronoiFeature {
+ NODE_VORONOI_F1,
+ NODE_VORONOI_F2,
+ NODE_VORONOI_F3,
+ NODE_VORONOI_F4,
+ NODE_VORONOI_F2F1
+} NodeVoronoiFeature;
+
typedef enum NodeBlendWeightType {
NODE_LAYER_WEIGHT_FRESNEL,
NODE_LAYER_WEIGHT_FACING
diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h
index 9bfb182544b..e5e350bf76a 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -18,121 +18,136 @@ CCL_NAMESPACE_BEGIN
/* Voronoi */
-ccl_device float voronoi_F1_distance(float3 p)
+ccl_device void voronoi_neighbors(float3 p, NodeVoronoiDistanceMetric distance, float e, float da[4], float3 pa[4])
{
- /* returns squared distance in da */
- float da = 1e10f;
+ /* Compute the distance to and the position of the closest neighbors to p.
+ *
+ * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
+ * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
+ * contain the distance to the closest point and its coordinates respectively.
+ */
-#ifndef __KERNEL_SSE2__
- int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
+ da[0] = 1e10f;
+ da[1] = 1e10f;
+ da[2] = 1e10f;
+ da[3] = 1e10f;
- for(int xx = -1; xx <= 1; xx++) {
- for(int yy = -1; yy <= 1; yy++) {
- for(int zz = -1; zz <= 1; zz++) {
- float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
- float3 vp = ip + cellnoise_color(ip);
- float d = len_squared(p - vp);
- da = min(d, da);
- }
- }
- }
-#else
- ssef vec_p = load4f(p);
- ssei xyzi = quick_floor_sse(vec_p);
+ int3 xyzi = quick_floor_to_int3(p);
for(int xx = -1; xx <= 1; xx++) {
for(int yy = -1; yy <= 1; yy++) {
for(int zz = -1; zz <= 1; zz++) {
- ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
- ssef vp = ip + cellnoise_color(ip);
- float d = len_squared<1, 1, 1, 0>(vec_p - vp);
- da = min(d, da);
+ int3 ip = xyzi + make_int3(xx, yy, zz);
+ float3 fp = make_float3(ip.x, ip.y, ip.z);
+ float3 vp = fp + cellnoise3(fp);
+
+ float d;
+ switch(distance) {
+ case NODE_VORONOI_DISTANCE:
+ d = len_squared(p - vp);
+ break;
+ case NODE_VORONOI_MANHATTAN:
+ d = reduce_add(fabs(vp - p));
+ break;
+ case NODE_VORONOI_CHEBYCHEV:
+ d = max3(fabs(vp - p));
+ break;
+ case NODE_VORONOI_MINKOWSKI:
+ float3 n = fabs(vp - p);
+ if(e == 0.5f) {
+ d = sqr(reduce_add(sqrt(n)));
+ }
+ else {
+ d = powf(reduce_add(pow3(n, e)), 1.0f/e);
+ }
+ break;
+ }
+
+ /* To keep the shortest four distances and associated points we have to keep them in sorted order. */
+ if (d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
}
}
}
-#endif
-
- return da;
}
-ccl_device float3 voronoi_F1_color(float3 p)
+ccl_device void svm_node_tex_voronoi(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- /* returns color of the nearest point */
- float da = 1e10f;
+ uint4 node2 = read_node(kg, offset);
-#ifndef __KERNEL_SSE2__
- float3 pa;
- int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z);
+ uint co_offset, coloring, distance, feature;
+ uint scale_offset, e_offset, fac_offset, color_offset;
- for(int xx = -1; xx <= 1; xx++) {
- for(int yy = -1; yy <= 1; yy++) {
- for(int zz = -1; zz <= 1; zz++) {
- float3 ip = make_float3(ix + xx, iy + yy, iz + zz);
- float3 vp = ip + cellnoise_color(ip);
- float d = len_squared(p - vp);
-
- if(d < da) {
- da = d;
- pa = vp;
- }
- }
- }
- }
+ decode_node_uchar4(node.y, &co_offset, &coloring, &distance, &feature);
+ decode_node_uchar4(node.z, &scale_offset, &e_offset, &fac_offset, &color_offset);
- return cellnoise_color(pa);
-#else
- ssef pa, vec_p = load4f(p);
- ssei xyzi = quick_floor_sse(vec_p);
+ float3 co = stack_load_float3(stack, co_offset);
+ float scale = stack_load_float_default(stack, scale_offset, node2.x);
+ float exponent = stack_load_float_default(stack, e_offset, node2.y);
- for(int xx = -1; xx <= 1; xx++) {
- for(int yy = -1; yy <= 1; yy++) {
- for(int zz = -1; zz <= 1; zz++) {
- ssef ip = ssef(xyzi + ssei(xx, yy, zz, 0));
- ssef vp = ip + cellnoise_color(ip);
- float d = len_squared<1, 1, 1, 0>(vec_p - vp);
+ float dist[4];
+ float3 neighbor[4];
+ voronoi_neighbors(co*scale, (NodeVoronoiDistanceMetric)distance, exponent, dist, neighbor);
- if(d < da) {
- da = d;
- pa = vp;
- }
- }
+ float3 color;
+ float fac;
+ if(coloring == NODE_VORONOI_INTENSITY) {
+ switch(feature) {
+ case NODE_VORONOI_F1: fac = dist[0]; break;
+ case NODE_VORONOI_F2: fac = dist[1]; break;
+ case NODE_VORONOI_F3: fac = dist[2]; break;
+ case NODE_VORONOI_F4: fac = dist[3]; break;
+ case NODE_VORONOI_F2F1: fac = dist[1] - dist[0]; break;
}
- }
- ssef color = cellnoise_color(pa);
- return (float3 &)color;
-#endif
-}
-
-ccl_device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float3 p)
-{
- if(coloring == NODE_VORONOI_INTENSITY) {
- /* compute squared distance to the nearest neighbour */
- float fac = voronoi_F1_distance(p);
- return make_float4(fac, fac, fac, fac);
+ color = make_float3(fac, fac, fac);
}
else {
- /* compute color of the nearest neighbour */
- float3 color = voronoi_F1_color(p);
- return make_float4(color.x, color.y, color.z, average(color));
- }
-}
-
-ccl_device void svm_node_tex_voronoi(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
-{
- uint coloring = node.y;
- uint scale_offset, co_offset, fac_offset, color_offset;
-
- decode_node_uchar4(node.z, &scale_offset, &co_offset, &fac_offset, &color_offset);
-
- float3 co = stack_load_float3(stack, co_offset);
- float scale = stack_load_float_default(stack, scale_offset, node.w);
+ /* NODE_VORONOI_CELLS */
+ switch(feature) {
+ case NODE_VORONOI_F1: color = neighbor[0]; break;
+ case NODE_VORONOI_F2: color = neighbor[1]; break;
+ case NODE_VORONOI_F3: color = neighbor[2]; break;
+ case NODE_VORONOI_F4: color = neighbor[3]; break;
+ /* Usefulness of this vector is questionable. Note F2 >= F1 but the
+ * individual vector components might not be. */
+ case NODE_VORONOI_F2F1: color = fabs(neighbor[1] - neighbor[0]); break;
+ }
- float4 result = svm_voronoi((NodeVoronoiColoring)coloring, co*scale);
- float3 color = make_float3(result.x, result.y, result.z);
- float f = result.w;
+ color = cellnoise3(color);
+ fac = average(color);
+ }
- if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f);
+ if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, fac);
if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, color);
}
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 868217f595b..e6bb341d1b8 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -913,7 +913,23 @@ NODE_DEFINE(VoronoiTextureNode)
coloring_enum.insert("cells", NODE_VORONOI_CELLS);
SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
+ static NodeEnum metric;
+ metric.insert("distance", NODE_VORONOI_DISTANCE);
+ metric.insert("manhattan", NODE_VORONOI_MANHATTAN);
+ metric.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
+ metric.insert("minkowski", NODE_VORONOI_MINKOWSKI);
+ SOCKET_ENUM(metric, "Distance Metric", metric, NODE_VORONOI_INTENSITY);
+
+ static NodeEnum feature_enum;
+ feature_enum.insert("F1", NODE_VORONOI_F1);
+ feature_enum.insert("F2", NODE_VORONOI_F2);
+ feature_enum.insert("F3", NODE_VORONOI_F3);
+ feature_enum.insert("F4", NODE_VORONOI_F4);
+ feature_enum.insert("F2F1", NODE_VORONOI_F2F1);
+ SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_INTENSITY);
+
SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
SOCKET_OUT_COLOR(color, "Color");
@@ -931,19 +947,32 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler)
{
ShaderInput *scale_in = input("Scale");
ShaderInput *vector_in = input("Vector");
+ ShaderInput *exponent_in = input("Exponent");
ShaderOutput *color_out = output("Color");
ShaderOutput *fac_out = output("Fac");
+ if (vector_in->link) compiler.stack_assign(vector_in);
+ if (scale_in->link) compiler.stack_assign(scale_in);
+ if (exponent_in->link) compiler.stack_assign(exponent_in);
+
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_VORONOI,
- coloring,
compiler.encode_uchar4(
- compiler.stack_assign_if_linked(scale_in),
vector_offset,
+ coloring,
+ metric,
+ feature
+ ),
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(exponent_in),
compiler.stack_assign(fac_out),
- compiler.stack_assign(color_out)),
- __float_as_int(scale));
+ compiler.stack_assign(color_out)
+ ));
+ compiler.add_node(
+ __float_as_int(scale),
+ __float_as_int(exponent));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -953,6 +982,8 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler)
tex_mapping.compile(compiler);
compiler.parameter(this, "coloring");
+ compiler.parameter(this, "metric");
+ compiler.parameter(this, "feature");
compiler.add(this, "node_voronoi_texture");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 860d50242e9..fd043ce5161 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -189,7 +189,9 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
NodeVoronoiColoring coloring;
- float scale;
+ NodeVoronoiDistanceMetric metric;
+ NodeVoronoiFeature feature;
+ float scale, exponent;
float3 vector;
};
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index fd3199f209f..85cbd18b7ba 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -266,6 +266,11 @@ ccl_device_inline int floor_to_int(float f)
return float_to_int(floorf(f));
}
+ccl_device_inline int quick_floor_to_int(float x)
+{
+ return float_to_int(x) - ((x < 0) ? 1 : 0);
+}
+
ccl_device_inline int ceil_to_int(float f)
{
return float_to_int(ceilf(f));
@@ -550,6 +555,11 @@ ccl_device_inline float xor_signmask(float x, int y)
return __int_as_float(__float_as_int(x) ^ y);
}
+ccl_device float bits_to_01(uint bits)
+{
+ return bits * (1.0f/(float)0xFFFFFFFF);
+}
+
/* projections */
ccl_device_inline float2 map_to_tube(const float3 co)
{
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index f5149fe13ed..3a5a2ab2244 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -280,6 +280,11 @@ ccl_device_inline float3 sqrt(const float3& a)
#endif
}
+ccl_device_inline float3 pow3(const float3& a, float e)
+{
+ return make_float3(powf(a.x, e), powf(a.y, e), powf(a.z, e));
+}
+
ccl_device_inline float3 mix(const float3& a, const float3& b, float t)
{
return a + t*(b - a);
@@ -377,6 +382,18 @@ ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
#endif
}
+ccl_device_inline int3 quick_floor_to_int3(const float3 a)
+{
+#ifdef __KERNEL_SSE__
+ int3 b = int3(_mm_cvttps_epi32(a.m128));
+ int3 isneg = int3(_mm_castps_si128(_mm_cmplt_ps(a.m128, _mm_set_ps1(0.0f))));
+ /* Unsaturated add 0xffffffff is the same as subtract -1. */
+ return b + isneg;
+#else
+ return make_int3(quick_floor_to_int(a.x), quick_floor_to_int(a.y), quick_floor_to_int(a.z));
+#endif
+}
+
ccl_device_inline bool isfinite3_safe(float3 v)
{
return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
diff --git a/intern/cycles/util/util_math_int3.h b/intern/cycles/util/util_math_int3.h
index 6eef8517665..81b10f31f4a 100644
--- a/intern/cycles/util/util_math_int3.h
+++ b/intern/cycles/util/util_math_int3.h
@@ -91,6 +91,24 @@ ccl_device_inline bool operator<(const int3 &a, const int3 &b)
{
return a.x < b.x && a.y < b.y && a.z < b.z;
}
+
+ccl_device_inline int3 operator+(const int3 &a, const int3 &b)
+{
+#ifdef __KERNEL_SSE__
+ return int3(_mm_add_epi32(a.m128, b.m128));
+#else
+ return make_int3(a.x + b.x, a.y + b.y, a.z + b.z);
+#endif
+}
+
+ccl_device_inline int3 operator-(const int3 &a, const int3 &b)
+{
+#ifdef __KERNEL_SSE__
+ return int3(_mm_sub_epi32(a.m128, b.m128));
+#else
+ return make_int3(a.x - b.x, a.y - b.y, a.z - b.z);
+#endif
+}
#endif /* !__KERNEL_OPENCL__ */
CCL_NAMESPACE_END
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 335c135cfba..33515ebc645 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -874,6 +874,8 @@ static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C),
static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "distance", 0, "", ICON_NONE);
+ uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
}
static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 3890d7b52cf..d1183c792f5 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2290,7 +2290,7 @@ void node_tex_sky(vec3 co, out vec4 color)
color = vec4(1.0);
}
-void node_tex_voronoi(vec3 co, float scale, float coloring, out vec4 color, out float fac)
+void node_tex_voronoi(vec3 co, float scale, float exponent, float coloring, out vec4 color, out float fac)
{
vec3 p = co * scale;
int xx, yy, zz, xi, yi, zi;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index d5cb32c90d9..ca01ffc2b29 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -776,6 +776,8 @@ typedef struct NodeTexNoise {
typedef struct NodeTexVoronoi {
NodeTexBase base;
int coloring;
+ int distance;
+ int feature;
int pad;
} NodeTexVoronoi;
@@ -974,17 +976,20 @@ typedef struct NodeSunBeams {
#define SHD_NOISE_HARD 1
/* voronoi texture */
-#define SHD_VORONOI_DISTANCE_SQUARED 0
-#define SHD_VORONOI_ACTUAL_DISTANCE 1
-#define SHD_VORONOI_MANHATTAN 2
-#define SHD_VORONOI_CHEBYCHEV 3
-#define SHD_VORONOI_MINKOVSKY_H 4
-#define SHD_VORONOI_MINKOVSKY_4 5
-#define SHD_VORONOI_MINKOVSKY 6
+#define SHD_VORONOI_DISTANCE 0
+#define SHD_VORONOI_MANHATTAN 1
+#define SHD_VORONOI_CHEBYCHEV 2
+#define SHD_VORONOI_MINKOWSKI 3
#define SHD_VORONOI_INTENSITY 0
#define SHD_VORONOI_CELLS 1
+#define SHD_VORONOI_F1 0
+#define SHD_VORONOI_F2 1
+#define SHD_VORONOI_F3 2
+#define SHD_VORONOI_F4 3
+#define SHD_VORONOI_F2F1 4
+
/* musgrave texture */
#define SHD_MUSGRAVE_MULTIFRACTAL 0
#define SHD_MUSGRAVE_FBM 1
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index ebae066db1c..c0eda3dc053 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3049,16 +3049,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
ED_node_tag_update_nodetree(bmain, ntree, node);
}
-static void rna_ShaderNodePrincipled_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
-
- nodeUpdate(ntree, node);
- rna_Node_update(bmain, scene, ptr);
-}
-
-static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->id.data;
bNode *node = (bNode *)ptr->data;
@@ -3941,6 +3932,23 @@ static void def_sh_tex_voronoi(StructRNA *srna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_distance_items[] = {
+ { SHD_VORONOI_DISTANCE, "DISTANCE", 0, "Distance", "Distance" },
+ { SHD_VORONOI_MANHATTAN, "MANHATTAN", 0, "Manhattan", "Manhattan (city block) distance" },
+ { SHD_VORONOI_CHEBYCHEV, "CHEBYCHEV", 0, "Chebychev", "Chebychev distance" },
+ { SHD_VORONOI_MINKOWSKI, "MINKOWSKI", 0, "Minkowski", "Minkowski distance" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
+ static EnumPropertyItem prop_feature_items[] = {
+ { SHD_VORONOI_F1, "F1", 0, "Closest", "Closest point" },
+ { SHD_VORONOI_F2, "F2", 0, "2nd Closest", "2nd closest point" },
+ { SHD_VORONOI_F3, "F3", 0, "3rd Closest", "3rd closest point" },
+ { SHD_VORONOI_F4, "F4", 0, "4th Closest", "4th closest point" },
+ { SHD_VORONOI_F2F1, "F2F1", 0, "Crackle", "Difference between 2nd and 1st closest point" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeTexVoronoi", "storage");
@@ -3951,6 +3959,18 @@ static void def_sh_tex_voronoi(StructRNA *srna)
RNA_def_property_enum_items(prop, prop_coloring_items);
RNA_def_property_ui_text(prop, "Coloring", "");
RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "distance", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "distance");
+ RNA_def_property_enum_items(prop, prop_distance_items);
+ RNA_def_property_ui_text(prop, "Distance metric", "");
+ RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
+
+ prop = RNA_def_property(srna, "feature", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "feature");
+ RNA_def_property_enum_items(prop, prop_feature_items);
+ RNA_def_property_ui_text(prop, "Feature Output", "");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
}
static void def_sh_tex_wave(StructRNA *srna)
@@ -4212,13 +4232,13 @@ static void def_principled(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, node_principled_distribution_items);
RNA_def_property_ui_text(prop, "Distribution", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "subsurface_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "custom2");
RNA_def_property_enum_items(prop, node_subsurface_method_items);
RNA_def_property_ui_text(prop, "Subsurface Method", "Method for rendering subsurface scattering");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
static void def_refraction(StructRNA *srna)
@@ -4453,7 +4473,7 @@ static void def_sh_subsurface(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, prop_subsurface_falloff_items);
RNA_def_property_ui_text(prop, "Falloff", "Function to determine how much light nearby points contribute based on their distance to the shading point");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
static void def_sh_tex_ies(StructRNA *srna)
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
index 36b6174059a..18d0dee8b88 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c
@@ -32,6 +32,7 @@
static bNodeSocketTemplate sh_node_tex_voronoi_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_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
+ { SOCK_FLOAT, 1, N_("Exponent"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 32.0f},
{ -1, 0, "" }
};
@@ -47,6 +48,8 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->coloring = SHD_VORONOI_INTENSITY;
+ tex->distance = SHD_VORONOI_DISTANCE;
+ tex->feature = SHD_VORONOI_F1;
node->storage = tex;
}
@@ -66,6 +69,23 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat, bNode *node, bNodeExecD
return GPU_stack_link(mat, node, "node_tex_voronoi", in, out, GPU_uniform(&coloring));
}
+static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
+ bNodeSocket *sock;
+
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Exponent")) {
+ if (tex->distance == SHD_VORONOI_MINKOWSKI) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+ }
+ }
+}
+
/* node type definition */
void register_node_type_sh_tex_voronoi(void)
{
@@ -76,6 +96,7 @@ void register_node_type_sh_tex_voronoi(void)
node_type_init(&ntype, node_shader_init_tex_voronoi);
node_type_storage(&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
node_type_gpu(&ntype, node_shader_gpu_tex_voronoi);
+ node_type_update(&ntype, node_shader_update_tex_voronoi, NULL);
nodeRegisterType(&ntype);
}