From 4697604331482c394c8a148c54a8e942120b634f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 14 Jul 2018 15:38:58 +0200 Subject: Cleanup: use float3 SSE instead of ssef for voronoi texture. --- intern/cycles/kernel/svm/svm_noise.h | 57 ++++++++++------------------------ intern/cycles/kernel/svm/svm_voronoi.h | 57 ++++++---------------------------- intern/cycles/util/util_math.h | 10 ++++++ intern/cycles/util/util_math_float3.h | 12 +++++++ intern/cycles/util/util_math_int3.h | 18 +++++++++++ 5 files changed, 67 insertions(+), 87 deletions(-) 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_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h index 9bfb182544b..5d0b8a2a406 100644 --- a/intern/cycles/kernel/svm/svm_voronoi.h +++ b/intern/cycles/kernel/svm/svm_voronoi.h @@ -23,34 +23,19 @@ ccl_device float voronoi_F1_distance(float3 p) /* returns squared distance in da */ float da = 1e10f; -#ifndef __KERNEL_SSE2__ - int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z); + 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++) { - float3 ip = make_float3(ix + xx, iy + yy, iz + zz); - float3 vp = ip + cellnoise_color(ip); + 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); } } } -#else - ssef vec_p = load4f(p); - ssei xyzi = quick_floor_sse(vec_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); - } - } - } -#endif return da; } @@ -59,37 +44,17 @@ ccl_device float3 voronoi_F1_color(float3 p) { /* returns color of the nearest point */ float da = 1e10f; - -#ifndef __KERNEL_SSE2__ float3 pa; - int ix = floor_to_int(p.x), iy = floor_to_int(p.y), iz = floor_to_int(p.z); - 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; - } - } - } - } - - return cellnoise_color(pa); -#else - ssef pa, 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); + 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); if(d < da) { da = d; @@ -99,9 +64,7 @@ ccl_device float3 voronoi_F1_color(float3 p) } } - ssef color = cellnoise_color(pa); - return (float3 &)color; -#endif + return cellnoise3(pa); } ccl_device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float3 p) 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..e42ded76c75 100644 --- a/intern/cycles/util/util_math_float3.h +++ b/intern/cycles/util/util_math_float3.h @@ -377,6 +377,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 -- cgit v1.2.3 From 83a4e1aaf9d1aa5e4747213dee5485945cecb05d Mon Sep 17 00:00:00 2001 From: charlie Date: Sat, 14 Jul 2018 13:11:28 +0200 Subject: 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 --- intern/cycles/blender/blender_shader.cpp | 2 + .../cycles/kernel/shaders/node_voronoi_texture.osl | 122 +++++++++++++++- intern/cycles/kernel/svm/svm_types.h | 15 ++ intern/cycles/kernel/svm/svm_voronoi.h | 156 ++++++++++++++------- intern/cycles/render/nodes.cpp | 39 +++++- intern/cycles/render/nodes.h | 4 +- intern/cycles/util/util_math_float3.h | 5 + source/blender/editors/space_node/drawnode.c | 2 + .../blender/gpu/shaders/gpu_shader_material.glsl | 2 +- source/blender/makesdna/DNA_node_types.h | 19 ++- source/blender/makesrna/intern/rna_nodetree.c | 46 ++++-- .../nodes/shader/nodes/node_shader_tex_voronoi.c | 21 +++ 12 files changed, 350 insertions(+), 83 deletions(-) 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; + 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; + } + + 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 fe2916d21d4..986004433e4 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 f24445ea2e9..ebe6db6e362 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_float3.h b/intern/cycles/util/util_math_float3.h index e42ded76c75..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); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index fff6c5d9f2c..b0440b39823 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -961,6 +961,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 2cb92fd1cbc..ab044fff100 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -3660,7 +3660,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) { #ifdef BIT_OPERATIONS vec3 p = co * scale; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index f6d92a95c3a..129172315dd 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -778,6 +778,8 @@ typedef struct NodeTexNoise { typedef struct NodeTexVoronoi { NodeTexBase base; int coloring; + int distance; + int feature; int pad; } NodeTexVoronoi; @@ -976,17 +978,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 5fe42e11765..e66c1e937e6 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3055,16 +3055,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; @@ -4003,6 +3994,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"); @@ -4013,6 +4021,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) @@ -4284,13 +4304,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) @@ -4525,7 +4545,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 8c5ddaafa1e..e5bf8f49717 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_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) { @@ -77,6 +97,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); } -- cgit v1.2.3