Commit: 83a4e1aaf9d1aa5e4747213dee5485945cecb05d
Author: charlie
Date:   Sat Jul 14 13:11:28 2018 +0200
Branches: master
https://developer.blender.org/rB83a4e1aaf9d1aa5e4747213dee5485945cecb05d

Cycles: add voronoi features and distance settings from Blender.

Features to get the 2nd, 3rd, 4th closest point instead of the closest, and
various distance metrics. No viewport/Eevee support yet.

Patch by Michel Anders, Charlie Jolly and Brecht Van Lommel.

Differential Revision: https://developer.blender.org/D3503

===================================================================

M       intern/cycles/blender/blender_shader.cpp
M       intern/cycles/kernel/shaders/node_voronoi_texture.osl
M       intern/cycles/kernel/svm/svm_types.h
M       intern/cycles/kernel/svm/svm_voronoi.h
M       intern/cycles/render/nodes.cpp
M       intern/cycles/render/nodes.h
M       intern/cycles/util/util_math_float3.h
M       source/blender/editors/space_node/drawnode.c
M       source/blender/gpu/shaders/gpu_shader_material.glsl
M       source/blender/makesdna/DNA_node_types.h
M       source/blender/makesrna/intern/rna_nodetree.c
M       source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c

===================================================================

diff --git a/intern/cycles/blender/blender_shader.cpp 
b/intern/cycles/blender/blender_shader.cpp
index 8afcb0ce885..956f8f767a6 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -748,6 +748,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_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 5d0b8a2a406..e5e350bf76a 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -18,10 +18,19 @@ 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.
+        */
+
+       da[0] = 1e10f;
+       da[1] = 1e10f;
+       da[2] = 1e10f;
+       da[3] = 1e10f;
 
        int3 xyzi = quick_floor_to_int3(p);
 
@@ -31,71 +40,114 @@ ccl_device float voronoi_F1_distance(float3 p)
                                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 = len_squared(p - vp);
-                               da = min(d, da);
-                       }
-               }
-       }
-
-       return da;
-}
 
-ccl_device float3 voronoi_F1_color(float3 p)
-{
-       /* returns color of the nearest point */
-       float da = 1e10f;
-       float3 pa;
-
-       int3 xyzi = quick_floor_to_int3(p);
+                               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;
+                               }
 
-       for(int xx = -1; xx <= 1; xx++) {
-               for(int yy = -1; yy <= 1; yy++) {
-                       for(int zz = -1; zz <= 1; zz++) {
-                               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 = len_squared(p - vp);
+                               /* 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;
 
-                               if(d < da) {
-                                       da = d;
-                                       pa = vp;
+                                       pa[3] = pa[2];
+                                       pa[2] = vp;
+                               }
+                               else if (d < da[3]) {
+                                       da[3] = d;
+                                       pa[3] = vp;
                                }
                        }
                }
        }
-
-       return cellnoise3(pa);
-}
-
-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);
-       }
-       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;
+       uint4 node2 = read_node(kg, offset);
+
+       uint co_offset, coloring, distance, feature;
+       uint scale_offset, e_offset, fac_offset, color_offset;
 
-       decode_node_uchar4(node.z, &scale_offset, &co_offset, &fac_offset, 
&color_offset);
+       decode_node_uchar4(node.y, &co_offset, &coloring, &distance, &feature);
+       decode_node_uchar4(node.z, &scale_offset, &e_offset, &fac_offset, 
&color_offset);
 
        float3 co = stack_load_float3(stack, co_offset);
-       float scale = stack_load_float_default(stack, scale_offset, node.w);
+       float scale = stack_load_float_default(stack, scale_offset, node2.x);
+       float exponent = stack_load_float_default(stack, e_offset, node2.y);
 
-       float4 result = svm_voronoi((NodeVoronoiColoring)coloring, co*scale);
-       float3 color = make_float3(result.x, result.y, result.z);
-       float f = result.w;
+       float dist[4];
+       float3 neighbor[4];
+       voronoi_neighbors(co*scale, (NodeVoronoiDistanceMetric)distance, 
exponent, dist, neighbor);
+
+       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;
+               }
+
+               color = make_float3(fac, fac, fac);
+       }
+       else {
+                /* NODE_VORONOI_CELLS */
+               switch(feature) {
+                       case NODE_VORONOI_F1: color = neighbor[0]; break;

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to