Shading: Add More Features To The Voronoi Node.

This patch allows the Voronoi node to operate in 1D, 2D, and 4D space.
It also adds a Randomness input to control the randomness of the texture.
Additionally, it adds three new modes of operation:

- Smooth F1: A smooth version of F1 Voronoi with no discontinuities.
- Distance To Edge: Returns the distance to the edges of the cells.
- N-Sphere Radius: Returns the radius of the n-sphere inscribed in
the cells. In other words, it is half the distance between the
closest feature point and the feature point closest to it.

And it removes the following three modes of operation:

- F3.
- F4.
- Cracks.

The Distance metric is now called Euclidean, and it computes the actual
euclidean distance as opposed to the old method of computing the squared
euclidean distance.

This breaks backward compatibility in many ways, including the base case.

Reviewers: brecht, JacquesLucke

Differential Revision: https://developer.blender.org/D5743
This commit is contained in:
OmarSquircleArt 2019-09-12 13:09:31 +02:00
parent 0137509476
commit 613b37bc2c
Notes: blender-bot 2023-02-14 03:00:45 +01:00
Referenced by issue #71496, Voronoi Texture difference
26 changed files with 3790 additions and 535 deletions

View File

@ -733,9 +733,9 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
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->dimensions = b_voronoi_node.voronoi_dimensions();
voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
node = voronoi;

View File

@ -134,20 +134,6 @@ ccl_device float schlick_fresnel(float u)
return m2 * m2 * m; // pow(m, 5)
}
ccl_device float smooth_step(float edge0, float edge1, float x)
{
float result;
if (x < edge0)
result = 0.0f;
else if (x >= edge1)
result = 1.0f;
else {
float t = (x - edge0) / (edge1 - edge0);
result = (3.0f - 2.0f * t) * (t * t);
}
return result;
}
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
ccl_device_forceinline float3
interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0)

View File

@ -97,6 +97,7 @@ set(SRC_OSL
set(SRC_OSL_HEADERS
node_color.h
node_fresnel.h
node_hash.h
node_noise.h
node_ramp_util.h
stdosl.h

View File

@ -0,0 +1,81 @@
#include "stdosl.h"
#include "vector2.h"
#include "vector4.h"
#define vector3 point
/* **** Hash a float or vector[234] into a float [0, 1] **** */
float hash_float_to_float(float k)
{
return hashnoise(k);
}
float hash_vector2_to_float(vector2 k)
{
return hashnoise(k.x, k.y);
}
float hash_vector3_to_float(vector3 k)
{
return hashnoise(k);
}
float hash_vector4_to_float(vector4 k)
{
return hashnoise(vector3(k.x, k.y, k.z), k.w);
}
/* **** Hash a vector[234] into a vector[234] [0, 1] **** */
vector2 hash_vector2_to_vector2(vector2 k)
{
return vector2(hash_vector2_to_float(k), hash_vector3_to_float(vector3(k.x, k.y, 1.0)));
}
vector3 hash_vector3_to_vector3(vector3 k)
{
return vector3(hash_vector3_to_float(k),
hash_vector4_to_float(vector4(k[0], k[1], k[2], 1.0)),
hash_vector4_to_float(vector4(k[0], k[1], k[2], 2.0)));
}
vector4 hash_vector4_to_vector4(vector4 k)
{
return vector4(hash_vector4_to_float(k),
hash_vector4_to_float(vector4(k.w, k.x, k.y, k.z)),
hash_vector4_to_float(vector4(k.z, k.w, k.x, k.y)),
hash_vector4_to_float(vector4(k.y, k.z, k.w, k.x)));
}
/* **** Hash a float or a vec[234] into a color [0, 1] **** */
color hash_float_to_color(float k)
{
return color(hash_float_to_float(k),
hash_vector2_to_float(vector2(k, 1.0)),
hash_vector2_to_float(vector2(k, 2.0)));
}
color hash_vector2_to_color(vector2 k)
{
return color(hash_vector2_to_float(k),
hash_vector3_to_float(vector3(k.x, k.y, 1.0)),
hash_vector3_to_float(vector3(k.x, k.y, 2.0)));
}
color hash_vector3_to_color(vector3 k)
{
return color(hash_vector3_to_float(k),
hash_vector4_to_float(vector4(k[0], k[1], k[2], 1.0)),
hash_vector4_to_float(vector4(k[0], k[1], k[2], 2.0)));
}
color hash_vector4_to_color(vector4 k)
{
return color(hash_vector4_to_float(k),
hash_vector4_to_float(vector4(k.z, k.x, k.w, k.y)),
hash_vector4_to_float(vector4(k.w, k.z, k.y, k.x)));
}
#undef vector3

File diff suppressed because it is too large Load Diff

View File

@ -429,7 +429,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
svm_node_tex_gradient(sd, stack, node);
break;
case NODE_TEX_VORONOI:
svm_node_tex_voronoi(kg, sd, stack, node, &offset);
svm_node_tex_voronoi(kg, sd, stack, node.y, node.z, node.w, &offset);
break;
case NODE_TEX_MUSGRAVE:
svm_node_tex_musgrave(kg, sd, stack, node.y, node.z, node.w, &offset);

View File

@ -590,28 +590,4 @@ ccl_device_inline float noise_4d(float4 p)
return 0.5f * snoise_4d(p) + 0.5f;
}
/* cell noise */
ccl_device float cellnoise(float3 p)
{
int3 ip = quick_floor_to_int3(p);
return hash_uint3_to_float(ip.x, ip.y, ip.z);
}
ccl_device float3 cellnoise3(float3 p)
{
int3 ip = quick_floor_to_int3(p);
#ifndef __KERNEL_SSE__
float r = hash_uint3_to_float(ip.x, ip.y, ip.z);
float g = hash_uint3_to_float(ip.y, ip.x, ip.z);
float b = hash_uint3_to_float(ip.y, ip.z, ip.x);
return make_float3(r, g, b);
#else
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_ssei3(ip_xyy, ip_yxz, ip_zzx);
return float3(uint32_to_float(bits) * ssef(1.0f / (float)0xFFFFFFFF));
#endif
}
CCL_NAMESPACE_END

View File

@ -357,24 +357,19 @@ typedef enum NodeGradientType {
NODE_BLEND_SPHERICAL
} NodeGradientType;
typedef enum NodeVoronoiColoring {
NODE_VORONOI_INTENSITY,
NODE_VORONOI_CELLS
} NodeVoronoiColoring;
typedef enum NodeVoronoiDistanceMetric {
NODE_VORONOI_DISTANCE,
NODE_VORONOI_EUCLIDEAN,
NODE_VORONOI_MANHATTAN,
NODE_VORONOI_CHEBYCHEV,
NODE_VORONOI_MINKOWSKI
NODE_VORONOI_MINKOWSKI,
} NodeVoronoiDistanceMetric;
typedef enum NodeVoronoiFeature {
NODE_VORONOI_F1,
NODE_VORONOI_F2,
NODE_VORONOI_F3,
NODE_VORONOI_F4,
NODE_VORONOI_F2F1
NODE_VORONOI_SMOOTH_F1,
NODE_VORONOI_DISTANCE_TO_EDGE,
NODE_VORONOI_N_SPHERE_RADIUS,
} NodeVoronoiFeature;
typedef enum NodeBlendWeightType {

File diff suppressed because it is too large Load Diff

View File

@ -965,33 +965,41 @@ NODE_DEFINE(VoronoiTextureNode)
TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
static NodeEnum coloring_enum;
coloring_enum.insert("intensity", NODE_VORONOI_INTENSITY);
coloring_enum.insert("cells", NODE_VORONOI_CELLS);
SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
static NodeEnum dimensions_enum;
dimensions_enum.insert("1D", 1);
dimensions_enum.insert("2D", 2);
dimensions_enum.insert("3D", 3);
dimensions_enum.insert("4D", 4);
SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 3);
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 metric_enum;
metric_enum.insert("euclidean", NODE_VORONOI_EUCLIDEAN);
metric_enum.insert("manhattan", NODE_VORONOI_MANHATTAN);
metric_enum.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
metric_enum.insert("minkowski", NODE_VORONOI_MINKOWSKI);
SOCKET_ENUM(metric, "Distance Metric", metric_enum, NODE_VORONOI_EUCLIDEAN);
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);
feature_enum.insert("f1", NODE_VORONOI_F1);
feature_enum.insert("f2", NODE_VORONOI_F2);
feature_enum.insert("smooth_f1", NODE_VORONOI_SMOOTH_F1);
feature_enum.insert("distance_to_edge", NODE_VORONOI_DISTANCE_TO_EDGE);
feature_enum.insert("n_sphere_radius", NODE_VORONOI_N_SPHERE_RADIUS);
SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_F1);
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_IN_FLOAT(w, "W", 0.0f);
SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
SOCKET_IN_FLOAT(smoothness, "Smoothness", 5.0f);
SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
SOCKET_IN_FLOAT(randomness, "Randomness", 1.0f);
SOCKET_OUT_FLOAT(distance, "Distance");
SOCKET_OUT_COLOR(color, "Color");
SOCKET_OUT_FLOAT(fac, "Fac");
SOCKET_OUT_POINT(position, "Position");
SOCKET_OUT_FLOAT(w, "W");
SOCKET_OUT_FLOAT(radius, "Radius");
return type;
}
@ -1002,39 +1010,57 @@ VoronoiTextureNode::VoronoiTextureNode() : TextureNode(node_type)
void VoronoiTextureNode::compile(SVMCompiler &compiler)
{
ShaderInput *scale_in = input("Scale");
ShaderInput *vector_in = input("Vector");
ShaderInput *w_in = input("W");
ShaderInput *scale_in = input("Scale");
ShaderInput *smoothness_in = input("Smoothness");
ShaderInput *exponent_in = input("Exponent");
ShaderInput *randomness_in = input("Randomness");
ShaderOutput *distance_out = output("Distance");
ShaderOutput *color_out = output("Color");
ShaderOutput *fac_out = output("Fac");
ShaderOutput *position_out = output("Position");
ShaderOutput *w_out = output("W");
ShaderOutput *radius_out = output("Radius");
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_stack_offset = tex_mapping.compile_begin(compiler, vector_in);
int w_in_stack_offset = compiler.stack_assign_if_linked(w_in);
int scale_stack_offset = compiler.stack_assign_if_linked(scale_in);
int smoothness_stack_offset = compiler.stack_assign_if_linked(smoothness_in);
int exponent_stack_offset = compiler.stack_assign_if_linked(exponent_in);
int randomness_stack_offset = compiler.stack_assign_if_linked(randomness_in);
int distance_stack_offset = compiler.stack_assign_if_linked(distance_out);
int color_stack_offset = compiler.stack_assign_if_linked(color_out);
int position_stack_offset = compiler.stack_assign_if_linked(position_out);
int w_out_stack_offset = compiler.stack_assign_if_linked(w_out);
int radius_stack_offset = compiler.stack_assign_if_linked(radius_out);
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_VORONOI, dimensions, feature, metric);
compiler.add_node(
compiler.encode_uchar4(
vector_stack_offset, w_in_stack_offset, scale_stack_offset, smoothness_stack_offset),
compiler.encode_uchar4(exponent_stack_offset,
randomness_stack_offset,
distance_stack_offset,
color_stack_offset),
compiler.encode_uchar4(position_stack_offset, w_out_stack_offset, radius_stack_offset),
__float_as_int(w));
compiler.add_node(NODE_TEX_VORONOI,
compiler.encode_uchar4(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)));
compiler.add_node(__float_as_int(scale), __float_as_int(exponent));
compiler.add_node(__float_as_int(scale),
__float_as_int(smoothness),
__float_as_int(exponent),
__float_as_int(randomness));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
tex_mapping.compile_end(compiler, vector_in, vector_stack_offset);
}
void VoronoiTextureNode::compile(OSLCompiler &compiler)
{
tex_mapping.compile(compiler);
compiler.parameter(this, "coloring");
compiler.parameter(this, "metric");
compiler.parameter(this, "dimensions");
compiler.parameter(this, "feature");
compiler.parameter(this, "metric");
compiler.add(this, "node_voronoi_texture");
}

View File

@ -220,10 +220,10 @@ class VoronoiTextureNode : public TextureNode {
return NODE_GROUP_LEVEL_2;
}
NodeVoronoiColoring coloring;
int dimensions;
NodeVoronoiDistanceMetric metric;
NodeVoronoiFeature feature;
float scale, exponent;
float w, scale, exponent, smoothness, randomness;
float3 vector;
};

View File

@ -294,6 +294,21 @@ ccl_device_inline float mix(float a, float b, float t)
{
return a + t * (b - a);
}
ccl_device_inline float smoothstep(float edge0, float edge1, float x)
{
float result;
if (x < edge0)
result = 0.0f;
else if (x >= edge1)
result = 1.0f;
else {
float t = (x - edge0) / (edge1 - edge0);
result = (3.0f - 2.0f * t) * (t * t);
}
return result;
}
#endif /* __KERNEL_OPENCL__ */
#ifndef __KERNEL_CUDA__

View File

@ -35,7 +35,9 @@ ccl_device_inline float2 operator*(float f, const float2 &a);
ccl_device_inline float2 operator/(float f, const float2 &a);
ccl_device_inline float2 operator/(const float2 &a, float f);
ccl_device_inline float2 operator/(const float2 &a, const float2 &b);
ccl_device_inline float2 operator+(const float2 &a, const float f);
ccl_device_inline float2 operator+(const float2 &a, const float2 &b);
ccl_device_inline float2 operator-(const float2 &a, const float f);
ccl_device_inline float2 operator-(const float2 &a, const float2 &b);
ccl_device_inline float2 operator+=(float2 &a, const float2 &b);
ccl_device_inline float2 operator*=(float2 &a, const float2 &b);
@ -48,6 +50,7 @@ ccl_device_inline bool operator!=(const float2 &a, const float2 &b);
ccl_device_inline bool is_zero(const float2 &a);
ccl_device_inline float average(const float2 &a);
ccl_device_inline float distance(const float2 &a, const float2 &b);
ccl_device_inline float dot(const float2 &a, const float2 &b);
ccl_device_inline float cross(const float2 &a, const float2 &b);
ccl_device_inline float len(const float2 &a);
@ -60,8 +63,11 @@ ccl_device_inline float2 clamp(const float2 &a, const float2 &mn, const float2 &
ccl_device_inline float2 fabs(const float2 &a);
ccl_device_inline float2 as_float2(const float4 &a);
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t);
ccl_device_inline float2 floor(const float2 &a);
#endif /* !__KERNEL_OPENCL__ */
ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b);
/*******************************************************************************
* Definition.
*/
@ -103,11 +109,21 @@ ccl_device_inline float2 operator/(const float2 &a, const float2 &b)
return make_float2(a.x / b.x, a.y / b.y);
}
ccl_device_inline float2 operator+(const float2 &a, const float f)
{
return a + make_float2(f, f);
}
ccl_device_inline float2 operator+(const float2 &a, const float2 &b)
{
return make_float2(a.x + b.x, a.y + b.y);
}
ccl_device_inline float2 operator-(const float2 &a, const float f)
{
return a - make_float2(f, f);
}
ccl_device_inline float2 operator-(const float2 &a, const float2 &b)
{
return make_float2(a.x - b.x, a.y - b.y);
@ -159,6 +175,11 @@ ccl_device_inline float average(const float2 &a)
return (a.x + a.y) * (1.0f / 2.0f);
}
ccl_device_inline float distance(const float2 &a, const float2 &b)
{
return len(a - b);
}
ccl_device_inline float dot(const float2 &a, const float2 &b)
{
return a.x * b.x + a.y * b.y;
@ -226,8 +247,18 @@ ccl_device_inline float2 mix(const float2 &a, const float2 &b, float t)
return a + t * (b - a);
}
ccl_device_inline float2 floor(const float2 &a)
{
return make_float2(floorf(a.x), floorf(a.y));
}
#endif /* !__KERNEL_OPENCL__ */
ccl_device_inline float2 safe_divide_float2_float(const float2 a, const float b)
{
return (b != 0.0f) ? a / b : make_float2(0.0f, 0.0f);
}
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_FLOAT2_H__ */

View File

@ -35,7 +35,9 @@ ccl_device_inline float3 operator*(const float f, const float3 &a);
ccl_device_inline float3 operator/(const float f, const float3 &a);
ccl_device_inline float3 operator/(const float3 &a, const float f);
ccl_device_inline float3 operator/(const float3 &a, const float3 &b);
ccl_device_inline float3 operator+(const float3 &a, const float f);
ccl_device_inline float3 operator+(const float3 &a, const float3 &b);
ccl_device_inline float3 operator-(const float3 &a, const float f);
ccl_device_inline float3 operator-(const float3 &a, const float3 &b);
ccl_device_inline float3 operator+=(float3 &a, const float3 &b);
ccl_device_inline float3 operator-=(float3 &a, const float3 &b);
@ -150,6 +152,11 @@ ccl_device_inline float3 operator/(const float3 &a, const float3 &b)
# endif
}
ccl_device_inline float3 operator+(const float3 &a, const float f)
{
return a + make_float3(f, f, f);
}
ccl_device_inline float3 operator+(const float3 &a, const float3 &b)
{
# ifdef __KERNEL_SSE__
@ -159,6 +166,11 @@ ccl_device_inline float3 operator+(const float3 &a, const float3 &b)
# endif
}
ccl_device_inline float3 operator-(const float3 &a, const float f)
{
return a - make_float3(f, f, f);
}
ccl_device_inline float3 operator-(const float3 &a, const float3 &b)
{
# ifdef __KERNEL_SSE__

View File

@ -34,7 +34,9 @@ ccl_device_inline float4 operator*(const float4 &a, float f);
ccl_device_inline float4 operator*(float f, const float4 &a);
ccl_device_inline float4 operator/(const float4 &a, float f);
ccl_device_inline float4 operator/(const float4 &a, const float4 &b);
ccl_device_inline float4 operator+(const float4 &a, const float f);
ccl_device_inline float4 operator+(const float4 &a, const float4 &b);
ccl_device_inline float4 operator-(const float4 &a, const float f);
ccl_device_inline float4 operator-(const float4 &a, const float4 &b);
ccl_device_inline float4 operator+=(float4 &a, const float4 &b);
ccl_device_inline float4 operator*=(float4 &a, const float4 &b);
@ -46,6 +48,7 @@ ccl_device_inline int4 operator>=(const float4 &a, const float4 &b);
ccl_device_inline int4 operator<=(const float4 &a, const float4 &b);
ccl_device_inline bool operator==(const float4 &a, const float4 &b);
ccl_device_inline float distance(const float4 &a, const float4 &b);
ccl_device_inline float dot(const float4 &a, const float4 &b);
ccl_device_inline float len_squared(const float4 &a);
ccl_device_inline float4 rcp(const float4 &a);
@ -61,8 +64,12 @@ ccl_device_inline float4 min(const float4 &a, const float4 &b);
ccl_device_inline float4 max(const float4 &a, const float4 &b);
ccl_device_inline float4 clamp(const float4 &a, const float4 &mn, const float4 &mx);
ccl_device_inline float4 fabs(const float4 &a);
ccl_device_inline float4 floor(const float4 &a);
ccl_device_inline float4 mix(const float4 &a, const float4 &b, float t);
#endif /* !__KERNEL_OPENCL__*/
ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b);
#ifdef __KERNEL_SSE__
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
__forceinline const float4 shuffle(const float4 &b);
@ -139,6 +146,11 @@ ccl_device_inline float4 operator/(const float4 &a, const float4 &b)
# endif
}
ccl_device_inline float4 operator+(const float4 &a, const float f)
{
return a + make_float4(f, f, f, f);
}
ccl_device_inline float4 operator+(const float4 &a, const float4 &b)
{
# ifdef __KERNEL_SSE__
@ -148,6 +160,11 @@ ccl_device_inline float4 operator+(const float4 &a, const float4 &b)
# endif
}
ccl_device_inline float4 operator-(const float4 &a, const float f)
{
return a - make_float4(f, f, f, f);
}
ccl_device_inline float4 operator-(const float4 &a, const float4 &b)
{
# ifdef __KERNEL_SSE__
@ -213,6 +230,11 @@ ccl_device_inline bool operator==(const float4 &a, const float4 &b)
# endif
}
ccl_device_inline float distance(const float4 &a, const float4 &b)
{
return len(a - b);
}
ccl_device_inline float dot(const float4 &a, const float4 &b)
{
# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
@ -338,6 +360,21 @@ ccl_device_inline float4 fabs(const float4 &a)
return make_float4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w));
# endif
}
ccl_device_inline float4 floor(const float4 &a)
{
# ifdef __KERNEL_SSE__
return float4(_mm_floor_ps(a));
# else
return make_float4(floorf(a.x), floorf(a.y), floorf(a.z), floorf(a.w));
# endif
}
ccl_device_inline float4 mix(const float4 &a, const float4 &b, float t)
{
return a + t * (b - a);
}
#endif /* !__KERNEL_OPENCL__*/
#ifdef __KERNEL_SSE__
@ -430,6 +467,11 @@ ccl_device_inline float4 load_float4(const float *v)
#endif /* !__KERNEL_GPU__ */
ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b)
{
return (b != 0.0f) ? a / b : make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_FLOAT4_H__ */

View File

@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 281
#define BLENDER_SUBVERSION 10
#define BLENDER_SUBVERSION 11
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0

View File

@ -946,6 +946,238 @@ static void update_musgrave_node_color_output(bNodeTree *ntree)
}
}
/* The Voronoi node now have a dimension property. This property should be
* initialized to 3 by default.
*/
static void update_voronoi_node_dimensions(bNodeTree *ntree)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_VORONOI) {
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
tex->dimensions = 3;
}
}
}
/* The F3 and F4 features of the Voronoi node have been removed.
* To correct this, we set the feature type to be F2 if it is F3
* or F4. The SHD_VORONOI_F3 and SHD_VORONOI_F4 enum values were
* 2 and 3 respectively.
*/
static void update_voronoi_node_f3_and_f4(bNodeTree *ntree)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_VORONOI) {
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
if (ELEM(tex->feature, 2, 3)) {
tex->feature = SHD_VORONOI_F2;
}
}
}
}
/* The Fac output of the Voronoi node has been removed. Previously, this
* output was the voronoi distance in the Intensity mode and the Cell ID
* in the Cell mode. To correct this, we update the identifier and name
* of the Fac socket such that it gets mapped to the Distance socket.
* This is supposed to work with update_voronoi_node_coloring.
*/
static void update_voronoi_node_fac_output(bNodeTree *ntree)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_VORONOI) {
bNodeSocket *facOutput = BLI_findlink(&node->outputs, 1);
strcpy(facOutput->identifier, "Distance");
strcpy(facOutput->name, "Distance");
}
}
}
/* The Crackle feature of the Voronoi node has been removed. Previously,
* this feature returned the F2 distance minus the F1 distance. The
* crackle feature had an enum value of 4. To fix this we do the
* following:
*
* 1. The node feature is set to F1.
* 2. A new Voronoi node is added and its feature is set to F2.
* 3. The properties, input values, and connections are copied
* from the node to the new Voronoi node so that they match
* exactly.
* 4. A Subtract node is added.
* 5. The outputs of the F1 and F2 voronoi are connected to
* the inputs of the subtract node.
* 6. The output of the subtract node is connected to the
* appropriate sockets.
*
*/
static void update_voronoi_node_crackle(bNodeTree *ntree)
{
bool need_update = false;
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_VORONOI) {
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
if (tex->feature == 4 && (socket_is_used(sockDistance) || socket_is_used(sockColor))) {
tex->feature = SHD_VORONOI_F1;
bNode *voronoiNode = nodeAddStaticNode(NULL, ntree, SH_NODE_TEX_VORONOI);
NodeTexVoronoi *texVoronoi = (NodeTexVoronoi *)voronoiNode->storage;
texVoronoi->feature = SHD_VORONOI_F2;
texVoronoi->distance = tex->distance;
texVoronoi->dimensions = 3;
voronoiNode->locx = node->locx + node->width + 20.0f;
voronoiNode->locy = node->locy;
bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
bNodeSocket *sockExponent = nodeFindSocket(node, SOCK_IN, "Exponent");
bNodeSocket *sockVoronoiVector = nodeFindSocket(voronoiNode, SOCK_IN, "Vector");
bNodeSocket *sockVoronoiScale = nodeFindSocket(voronoiNode, SOCK_IN, "Scale");
bNodeSocket *sockVoronoiExponent = nodeFindSocket(voronoiNode, SOCK_IN, "Exponent");
if (sockVector->link) {
nodeAddLink(ntree,
sockVector->link->fromnode,
sockVector->link->fromsock,
voronoiNode,
sockVoronoiVector);
}
*cycles_node_socket_float_value(sockVoronoiScale) = *cycles_node_socket_float_value(
sockScale);
if (sockScale->link) {
nodeAddLink(ntree,
sockScale->link->fromnode,
sockScale->link->fromsock,
voronoiNode,
sockVoronoiScale);
}
*cycles_node_socket_float_value(sockVoronoiExponent) = *cycles_node_socket_float_value(
sockExponent);
if (sockExponent->link) {
nodeAddLink(ntree,
sockExponent->link->fromnode,
sockExponent->link->fromsock,
voronoiNode,
sockVoronoiExponent);
}
bNode *subtractNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
subtractNode->custom1 = NODE_MATH_SUBTRACT;
subtractNode->locx = voronoiNode->locx + voronoiNode->width + 20.0f;
subtractNode->locy = voronoiNode->locy;
bNodeSocket *sockSubtractOutValue = nodeFindSocket(subtractNode, SOCK_OUT, "Value");
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromnode == node) {
nodeAddLink(ntree, subtractNode, sockSubtractOutValue, link->tonode, link->tosock);
nodeRemLink(ntree, link);
}
}
bNodeSocket *sockDistanceF1 = nodeFindSocket(node, SOCK_OUT, "Distance");
bNodeSocket *sockDistanceF2 = nodeFindSocket(voronoiNode, SOCK_OUT, "Distance");
bNodeSocket *sockSubtractA = BLI_findlink(&subtractNode->inputs, 0);
bNodeSocket *sockSubtractB = BLI_findlink(&subtractNode->inputs, 1);
nodeAddLink(ntree, node, sockDistanceF1, subtractNode, sockSubtractB);
nodeAddLink(ntree, voronoiNode, sockDistanceF2, subtractNode, sockSubtractA);
need_update = true;
}
}
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
}
}
/* The coloring property of the Voronoi node was removed. Previously,
* if the coloring enum was set to Intensity (0), the voronoi distance
* was returned in all outputs, otherwise, the Cell ID was returned.
* Since we remapped the Fac output in update_voronoi_node_fac_output,
* then to fix this, we relink the Color output to the Distance
* output if coloring was set to 0, and the otherway around otherwise.
*/
static void update_voronoi_node_coloring(bNodeTree *ntree)
{
bool need_update = false;
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
bNode *node = link->fromnode;
if (node && node->type == SH_NODE_TEX_VORONOI) {
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
if (tex->coloring == 0) {
bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
if (link->fromsock == sockColor) {
bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
nodeAddLink(ntree, node, sockDistance, link->tonode, link->tosock);
nodeRemLink(ntree, link);
need_update = true;
}
}
else {
bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
if (link->fromsock == sockDistance) {
bNodeSocket *sockColor = nodeFindSocket(node, SOCK_OUT, "Color");
nodeAddLink(ntree, node, sockColor, link->tonode, link->tosock);
nodeRemLink(ntree, link);
need_update = true;
}
}
}
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
}
}
/* Previously, the output euclidean distance was actually the squared
* euclidean distance. To fix this, we square the the output distance
* socket if the distance metric is set to SHD_VORONOI_EUCLIDEAN.
*/
static void update_voronoi_node_square_distance(bNodeTree *ntree)
{
bool need_update = false;
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_VORONOI) {
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
bNodeSocket *sockDistance = nodeFindSocket(node, SOCK_OUT, "Distance");
if (tex->distance == SHD_VORONOI_EUCLIDEAN &&
(tex->feature == SHD_VORONOI_F1 || tex->feature == SHD_VORONOI_F2) &&
socket_is_used(sockDistance)) {
bNode *multiplyNode = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
multiplyNode->custom1 = NODE_MATH_MULTIPLY;
multiplyNode->locx = node->locx + node->width + 20.0f;
multiplyNode->locy = node->locy;
bNodeSocket *sockValue = nodeFindSocket(multiplyNode, SOCK_OUT, "Value");
LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromsock == sockDistance) {
nodeAddLink(ntree, multiplyNode, sockValue, link->tonode, link->tosock);
nodeRemLink(ntree, link);
}
}
bNodeSocket *sockMultiplyA = BLI_findlink(&multiplyNode->inputs, 0);
bNodeSocket *sockMultiplyB = BLI_findlink(&multiplyNode->inputs, 1);
nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyA);
nodeAddLink(ntree, node, sockDistance, multiplyNode, sockMultiplyB);
need_update = true;
}
}
}
if (need_update) {
ntreeUpdateTree(NULL, ntree);
}
}
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@ -996,6 +1228,16 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
update_voronoi_node_f3_and_f4(ntree);
update_voronoi_node_fac_output(ntree);
}
}
FOREACH_NODETREE_END;
}
}
void do_versions_after_linking_cycles(Main *bmain)
@ -1154,4 +1396,16 @@ void do_versions_after_linking_cycles(Main *bmain)
}
FOREACH_NODETREE_END;
}
if (!MAIN_VERSION_ATLEAST(bmain, 281, 11)) {
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
if (ntree->type == NTREE_SHADER) {
update_voronoi_node_dimensions(ntree);
update_voronoi_node_crackle(ntree);
update_voronoi_node_coloring(ntree);
update_voronoi_node_square_distance(ntree);
}
}
FOREACH_NODETREE_END;
}
}

View File

@ -914,9 +914,13 @@ 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, "voronoi_dimensions", 0, "", ICON_NONE);
uiItemR(layout, ptr, "feature", 0, "", ICON_NONE);
int feature = RNA_enum_get(ptr, "feature");
if (!ELEM(feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS) &&
RNA_enum_get(ptr, "voronoi_dimensions") != 1) {
uiItemR(layout, ptr, "distance", 0, "", ICON_NONE);
}
}
static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)

View File

@ -243,7 +243,6 @@ data_to_c_simple(shaders/material/gpu_shader_material_blackbody.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_bright_contrast.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_bump.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_camera.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_cell_noise.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_clamp.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_color_ramp.glsl SRC)
data_to_c_simple(shaders/material/gpu_shader_material_color_util.glsl SRC)

View File

@ -44,7 +44,6 @@ extern char datatoc_gpu_shader_material_blackbody_glsl[];
extern char datatoc_gpu_shader_material_bright_contrast_glsl[];
extern char datatoc_gpu_shader_material_bump_glsl[];
extern char datatoc_gpu_shader_material_camera_glsl[];
extern char datatoc_gpu_shader_material_cell_noise_glsl[];
extern char datatoc_gpu_shader_material_clamp_glsl[];
extern char datatoc_gpu_shader_material_color_ramp_glsl[];
extern char datatoc_gpu_shader_material_color_util_glsl[];
@ -149,13 +148,6 @@ static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = {
.dependencies = {&gpu_shader_material_noise_library, NULL},
};
static GPUMaterialLibrary gpu_shader_material_cell_noise_library = {
.code = datatoc_gpu_shader_material_cell_noise_glsl,
.dependencies = {&gpu_shader_material_math_util_library,
&gpu_shader_material_hash_library,
NULL},
};
static GPUMaterialLibrary gpu_shader_material_add_shader_library = {
.code = datatoc_gpu_shader_material_add_shader_glsl,
.dependencies = {NULL},
@ -481,7 +473,7 @@ static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = {
static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = {
.code = datatoc_gpu_shader_material_tex_voronoi_glsl,
.dependencies = {&gpu_shader_material_math_util_library,
&gpu_shader_material_cell_noise_library,
&gpu_shader_material_hash_library,
NULL},
};
@ -571,7 +563,6 @@ static GPUMaterialLibrary *gpu_material_libraries[] = {
&gpu_shader_material_hash_library,
&gpu_shader_material_noise_library,
&gpu_shader_material_fractal_noise_library,
&gpu_shader_material_cell_noise_library,
&gpu_shader_material_add_shader_library,
&gpu_shader_material_ambient_occlusion_library,
&gpu_shader_material_glossy_library,

View File

@ -1,17 +0,0 @@
float cellnoise(vec3 p)
{
int ix = quick_floor(p.x);
int iy = quick_floor(p.y);
int iz = quick_floor(p.z);
return hash_uint3_to_float(uint(ix), uint(iy), uint(iz));
}
vec3 cellnoise_color(vec3 p)
{
float r = cellnoise(p.xyz);
float g = cellnoise(p.yxz);
float b = cellnoise(p.yzx);
return vec3(r, g, b);
}

View File

@ -57,11 +57,37 @@ float floorfrac(float x, out int i)
/* Vector Math */
vec2 safe_divide(vec2 a, vec2 b)
{
return vec2(safe_divide(a.x, b.x), safe_divide(a.y, b.y));
}
vec3 safe_divide(vec3 a, vec3 b)
{
return vec3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z));
}
vec4 safe_divide(vec4 a, vec4 b)
{
return vec4(
safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z), safe_divide(a.w, b.w));
}
vec2 safe_divide(vec2 a, float b)
{
return (b != 0.0) ? a / b : vec2(0.0);
}
vec3 safe_divide(vec3 a, float b)
{
return (b != 0.0) ? a / b : vec3(0.0);
}
vec4 safe_divide(vec4 a, float b)
{
return (b != 0.0) ? a / b : vec4(0.0);
}
vec3 c_mod(vec3 a, vec3 b)
{
return vec3(c_mod(a.x, b.x), c_mod(a.y, b.y), c_mod(a.z, b.z));

View File

@ -876,10 +876,10 @@ typedef struct NodeTexNoise {
typedef struct NodeTexVoronoi {
NodeTexBase base;
int coloring;
int distance;
int dimensions;
int feature;
char _pad[4];
int distance;
int coloring DNA_DEPRECATED;
} NodeTexVoronoi;
typedef struct NodeTexMusgrave {
@ -1098,20 +1098,22 @@ typedef struct NodeDenoise {
#define SHD_NOISE_SOFT 0
#define SHD_NOISE_HARD 1
/* voronoi texture */
#define SHD_VORONOI_DISTANCE 0
#define SHD_VORONOI_MANHATTAN 1
#define SHD_VORONOI_CHEBYCHEV 2
#define SHD_VORONOI_MINKOWSKI 3
/* Voronoi Texture */
#define SHD_VORONOI_INTENSITY 0
#define SHD_VORONOI_CELLS 1
enum {
SHD_VORONOI_EUCLIDEAN = 0,
SHD_VORONOI_MANHATTAN = 1,
SHD_VORONOI_CHEBYCHEV = 2,
SHD_VORONOI_MINKOWSKI = 3,
};
#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
enum {
SHD_VORONOI_F1 = 0,
SHD_VORONOI_F2 = 1,
SHD_VORONOI_SMOOTH_F1 = 2,
SHD_VORONOI_DISTANCE_TO_EDGE = 3,
SHD_VORONOI_N_SPHERE_RADIUS = 4,
};
/* musgrave texture */
#define SHD_MUSGRAVE_MULTIFRACTAL 0

View File

@ -4404,25 +4404,39 @@ static void def_sh_tex_musgrave(StructRNA *srna)
static void def_sh_tex_voronoi(StructRNA *srna)
{
static const EnumPropertyItem prop_coloring_items[] = {
{SHD_VORONOI_INTENSITY, "INTENSITY", 0, "Intensity", "Only calculate intensity"},
{SHD_VORONOI_CELLS, "CELLS", 0, "Cells", "Color cells by position"},
{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_EUCLIDEAN, "EUCLIDEAN", 0, "Euclidean", "Euclidean distance"},
{SHD_VORONOI_MANHATTAN, "MANHATTAN", 0, "Manhattan", "Manhattan 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"},
{SHD_VORONOI_F1,
"F1",
0,
"F1",
"Computes the distance to the closest point as well as its position and color"},
{SHD_VORONOI_F2,
"F2",
0,
"F2",
"Computes the distance to the second closest point as well as its position and color"},
{SHD_VORONOI_SMOOTH_F1,
"SMOOTH_F1",
0,
"Smooth F1",
"Smoothed version of F1. Weighted sum of neighbour voronoi cells"},
{SHD_VORONOI_DISTANCE_TO_EDGE,
"DISTANCE_TO_EDGE",
0,
"Distance To Edge",
"Computes the distance to the edge of the vornoi cell"},
{SHD_VORONOI_N_SPHERE_RADIUS,
"N_SPHERE_RADIUS",
0,
"N-Sphere Radius",
"Computes the radius of the n-sphere inscribed in the voronoi cell"},
{0, NULL, 0, NULL, NULL}};
PropertyRNA *prop;
@ -4430,11 +4444,11 @@ static void def_sh_tex_voronoi(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeTexVoronoi", "storage");
def_sh_tex(srna);
prop = RNA_def_property(srna, "coloring", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "coloring");
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, "voronoi_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", "");
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "distance", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "distance");
@ -4446,7 +4460,7 @@ static void def_sh_tex_voronoi(StructRNA *srna)
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");
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
}
static void def_sh_tex_wave(StructRNA *srna)

View File

@ -23,12 +23,26 @@
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_("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_("Smoothness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, 1, N_("Exponent"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 32.0f},
{SOCK_FLOAT, 1, N_("Randomness"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{-1, 0, ""},
};
static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
{SOCK_FLOAT,
0,
N_("Distance"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{SOCK_RGBA,
0,
N_("Color"),
@ -40,16 +54,28 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = {
1.0f,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT,
{SOCK_VECTOR,
0,
N_("Fac"),
N_("Position"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
PROP_FACTOR,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT, 0, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{SOCK_FLOAT,
0,
N_("Radius"),
0.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
PROP_NONE,
SOCK_NO_INTERNAL_LINK},
{-1, 0, ""},
};
@ -59,8 +85,8 @@ static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi");
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->dimensions = 3;
tex->distance = SHD_VORONOI_EUCLIDEAN;
tex->feature = SHD_VORONOI_F1;
node->storage = tex;
@ -75,39 +101,96 @@ static int node_shader_gpu_tex_voronoi(GPUMaterial *mat,
node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
node_shader_gpu_tex_mapping(mat, node, in, out);
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
float coloring = tex->coloring;
float metric = tex->distance;
float feature = tex->feature;
static const char *names[][5] = {
[SHD_VORONOI_F1] =
{
"",
"node_tex_voronoi_f1_1d",
"node_tex_voronoi_f1_2d",
"node_tex_voronoi_f1_3d",
"node_tex_voronoi_f1_4d",
},
[SHD_VORONOI_F2] =
{
"",
"node_tex_voronoi_f2_1d",
"node_tex_voronoi_f2_2d",
"node_tex_voronoi_f2_3d",
"node_tex_voronoi_f2_4d",
},
[SHD_VORONOI_SMOOTH_F1] =
{
"",
"node_tex_voronoi_smooth_f1_1d",
"node_tex_voronoi_smooth_f1_2d",
"node_tex_voronoi_smooth_f1_3d",
"node_tex_voronoi_smooth_f1_4d",
},
[SHD_VORONOI_DISTANCE_TO_EDGE] =
{
"",
"node_tex_voronoi_distance_to_edge_1d",
"node_tex_voronoi_distance_to_edge_2d",
"node_tex_voronoi_distance_to_edge_3d",
"node_tex_voronoi_distance_to_edge_4d",
},
[SHD_VORONOI_N_SPHERE_RADIUS] =
{
"",
"node_tex_voronoi_n_sphere_radius_1d",
"node_tex_voronoi_n_sphere_radius_2d",
"node_tex_voronoi_n_sphere_radius_3d",
"node_tex_voronoi_n_sphere_radius_4d",
},
};
return GPU_stack_link(mat,
node,
"node_tex_voronoi",
in,
out,
GPU_constant(&coloring),
GPU_constant(&metric),
GPU_constant(&feature));
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
float metric = tex->distance;
BLI_assert(tex->feature >= 0 && tex->feature < 5);
BLI_assert(tex->dimensions > 0 && tex->dimensions < 5);
return GPU_stack_link(
mat, node, names[tex->feature][tex->dimensions], in, out, GPU_constant(&metric));
}
static void node_shader_update_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
bNodeSocket *sock;
bNodeSocket *inVectorSock = nodeFindSocket(node, SOCK_IN, "Vector");
bNodeSocket *inWSock = nodeFindSocket(node, SOCK_IN, "W");
bNodeSocket *inSmoothnessSock = nodeFindSocket(node, SOCK_IN, "Smoothness");
bNodeSocket *inExponentSock = nodeFindSocket(node, SOCK_IN, "Exponent");
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;
}
}
}
bNodeSocket *outDistanceSock = nodeFindSocket(node, SOCK_OUT, "Distance");
bNodeSocket *outColorSock = nodeFindSocket(node, SOCK_OUT, "Color");
bNodeSocket *outPositionSock = nodeFindSocket(node, SOCK_OUT, "Position");
bNodeSocket *outWSock = nodeFindSocket(node, SOCK_OUT, "W");
bNodeSocket *outRadiusSock = nodeFindSocket(node, SOCK_OUT, "Radius");
NodeTexVoronoi *tex = (NodeTexVoronoi *)node->storage;
nodeSetSocketAvailability(inWSock, tex->dimensions == 1 || tex->dimensions == 4);
nodeSetSocketAvailability(inVectorSock, tex->dimensions != 1);
nodeSetSocketAvailability(
inExponentSock,
tex->distance == SHD_VORONOI_MINKOWSKI && tex->dimensions != 1 &&
!ELEM(tex->feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS));
nodeSetSocketAvailability(inSmoothnessSock, tex->feature == SHD_VORONOI_SMOOTH_F1);
nodeSetSocketAvailability(outDistanceSock, tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
nodeSetSocketAvailability(outColorSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS);
nodeSetSocketAvailability(outPositionSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
tex->dimensions != 1);
nodeSetSocketAvailability(outWSock,
tex->feature != SHD_VORONOI_DISTANCE_TO_EDGE &&
tex->feature != SHD_VORONOI_N_SPHERE_RADIUS &&
(tex->dimensions == 1 || tex->dimensions == 4));
nodeSetSocketAvailability(outRadiusSock, tex->feature == SHD_VORONOI_N_SPHERE_RADIUS);
}
/* node type definition */
void register_node_type_sh_tex_voronoi(void)
{
static bNodeType ntype;