From 4468c343787471df8a7a71ceb066301d2eaa6dc6 Mon Sep 17 00:00:00 2001 From: Charlie Jolly Date: Sun, 24 Oct 2021 22:15:30 +0100 Subject: [PATCH] Geometry Nodes: Optimise Voronoi texture node This patch improves performance by only assigning or calculating data for connected sockets. It is recommended that artists use the lowest dimensions setting for noise based textures. E.g. Use 2D instead of 3D where possible. Using a scoped timer and single thread on 256,000 points. Smooth F1 3D : Debug build Timer 'Optimised' took 9.39991 s Timer 'Normal' took 16.1531 s This optimisation is only for GN and not shaders. Differential Revision: https://developer.blender.org/D12985 --- source/blender/blenlib/intern/noise.cc | 204 ++++++-- .../shader/nodes/node_shader_tex_voronoi.cc | 483 +++++++++++++----- 2 files changed, 512 insertions(+), 175 deletions(-) diff --git a/source/blender/blenlib/intern/noise.cc b/source/blender/blenlib/intern/noise.cc index 5fa2746d07f..4259237af6e 100644 --- a/source/blender/blenlib/intern/noise.cc +++ b/source/blender/blenlib/intern/noise.cc @@ -1528,9 +1528,15 @@ void voronoi_f1( targetPosition = pointPosition; } } - *r_distance = minDistance; - *r_color = hash_float_to_float3(cellPosition + targetOffset); - *r_w = targetPosition + cellPosition; + if (r_distance != nullptr) { + *r_distance = minDistance; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + targetOffset); + } + if (r_w != nullptr) { + *r_w = targetPosition + cellPosition; + } } void voronoi_smooth_f1(const float w, @@ -1555,14 +1561,26 @@ void voronoi_smooth_f1(const float w, 0.0f, 1.0f, 0.5f + 0.5f * (smoothDistance - distanceToPoint) / smoothness); float correctionFactor = smoothness * h * (1.0f - h); smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor; - correctionFactor /= 1.0f + 3.0f * smoothness; - const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); - smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; - smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor; + if (r_color != nullptr || r_w != nullptr) { + correctionFactor /= 1.0f + 3.0f * smoothness; + if (r_color != nullptr) { + const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); + smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; + } + if (r_w != nullptr) { + smoothPosition = mix(smoothPosition, pointPosition, h) - correctionFactor; + } + } + } + if (r_distance != nullptr) { + *r_distance = smoothDistance; + } + if (r_color != nullptr) { + *r_color = smoothColor; + } + if (r_w != nullptr) { + *r_w = cellPosition + smoothPosition; } - *r_distance = smoothDistance; - *r_color = smoothColor; - *r_w = cellPosition + smoothPosition; } void voronoi_f2( @@ -1596,9 +1614,15 @@ void voronoi_f2( positionF2 = pointPosition; } } - *r_distance = distanceF2; - *r_color = hash_float_to_float3(cellPosition + offsetF2); - *r_w = positionF2 + cellPosition; + if (r_distance != nullptr) { + *r_distance = distanceF2; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + offsetF2); + } + if (r_w != nullptr) { + *r_w = positionF2 + cellPosition; + } } void voronoi_distance_to_edge(const float w, const float randomness, float *r_distance) @@ -1706,9 +1730,15 @@ void voronoi_f1(const float2 coord, } } } - *r_distance = minDistance; - *r_color = hash_float_to_float3(cellPosition + targetOffset); - *r_position = targetPosition + cellPosition; + if (r_distance != nullptr) { + *r_distance = minDistance; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + targetOffset); + } + if (r_position != nullptr) { + *r_position = targetPosition + cellPosition; + } } void voronoi_smooth_f1(const float2 coord, @@ -1737,15 +1767,28 @@ void voronoi_smooth_f1(const float2 coord, 0.0f, 1.0f, 0.5f + 0.5f * (smoothDistance - distanceToPoint) / smoothness); float correctionFactor = smoothness * h * (1.0f - h); smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor; - correctionFactor /= 1.0f + 3.0f * smoothness; - const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); - smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; - smoothPosition = float2::interpolate(smoothPosition, pointPosition, h) - correctionFactor; + if (r_color != nullptr || r_position != nullptr) { + correctionFactor /= 1.0f + 3.0f * smoothness; + if (r_color != nullptr) { + const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); + smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; + } + if (r_position != nullptr) { + smoothPosition = float2::interpolate(smoothPosition, pointPosition, h) - + correctionFactor; + } + } } } - *r_distance = smoothDistance; - *r_color = smoothColor; - *r_position = cellPosition + smoothPosition; + if (r_distance != nullptr) { + *r_distance = smoothDistance; + } + if (r_color != nullptr) { + *r_color = smoothColor; + } + if (r_position != nullptr) { + *r_position = cellPosition + smoothPosition; + } } void voronoi_f2(const float2 coord, @@ -1787,9 +1830,15 @@ void voronoi_f2(const float2 coord, } } } - *r_distance = distanceF2; - *r_color = hash_float_to_float3(cellPosition + offsetF2); - *r_position = positionF2 + cellPosition; + if (r_distance != nullptr) { + *r_distance = distanceF2; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + offsetF2); + } + if (r_position != nullptr) { + *r_position = positionF2 + cellPosition; + } } void voronoi_distance_to_edge(const float2 coord, const float randomness, float *r_distance) @@ -1928,9 +1977,15 @@ void voronoi_f1(const float3 coord, } } } - *r_distance = minDistance; - *r_color = hash_float_to_float3(cellPosition + targetOffset); - *r_position = targetPosition + cellPosition; + if (r_distance != nullptr) { + *r_distance = minDistance; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + targetOffset); + } + if (r_position != nullptr) { + *r_position = targetPosition + cellPosition; + } } void voronoi_smooth_f1(const float3 coord, @@ -1960,16 +2015,29 @@ void voronoi_smooth_f1(const float3 coord, 0.0f, 1.0f, 0.5f + 0.5f * (smoothDistance - distanceToPoint) / smoothness); float correctionFactor = smoothness * h * (1.0f - h); smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor; - correctionFactor /= 1.0f + 3.0f * smoothness; - const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); - smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; - smoothPosition = float3::interpolate(smoothPosition, pointPosition, h) - correctionFactor; + if (r_color != nullptr || r_position != nullptr) { + correctionFactor /= 1.0f + 3.0f * smoothness; + if (r_color != nullptr) { + const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); + smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; + } + if (r_position != nullptr) { + smoothPosition = float3::interpolate(smoothPosition, pointPosition, h) - + correctionFactor; + } + } } } } - *r_distance = smoothDistance; - *r_color = smoothColor; - *r_position = cellPosition + smoothPosition; + if (r_distance != nullptr) { + *r_distance = smoothDistance; + } + if (r_color != nullptr) { + *r_color = smoothColor; + } + if (r_position != nullptr) { + *r_position = cellPosition + smoothPosition; + } } void voronoi_f2(const float3 coord, @@ -2013,9 +2081,15 @@ void voronoi_f2(const float3 coord, } } } - *r_distance = distanceF2; - *r_color = hash_float_to_float3(cellPosition + offsetF2); - *r_position = positionF2 + cellPosition; + if (r_distance != nullptr) { + *r_distance = distanceF2; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + offsetF2); + } + if (r_position != nullptr) { + *r_position = positionF2 + cellPosition; + } } void voronoi_distance_to_edge(const float3 coord, const float randomness, float *r_distance) @@ -2166,9 +2240,15 @@ void voronoi_f1(const float4 coord, } } } - *r_distance = minDistance; - *r_color = hash_float_to_float3(cellPosition + targetOffset); - *r_position = targetPosition + cellPosition; + if (r_distance != nullptr) { + *r_distance = minDistance; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + targetOffset); + } + if (r_position != nullptr) { + *r_position = targetPosition + cellPosition; + } } void voronoi_smooth_f1(const float4 coord, @@ -2200,18 +2280,30 @@ void voronoi_smooth_f1(const float4 coord, 0.0f, 1.0f, 0.5f + 0.5f * (smoothDistance - distanceToPoint) / smoothness); float correctionFactor = smoothness * h * (1.0f - h); smoothDistance = mix(smoothDistance, distanceToPoint, h) - correctionFactor; - correctionFactor /= 1.0f + 3.0f * smoothness; - const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); - smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; - smoothPosition = float4::interpolate(smoothPosition, pointPosition, h) - - correctionFactor; + if (r_color != nullptr || r_position != nullptr) { + correctionFactor /= 1.0f + 3.0f * smoothness; + if (r_color != nullptr) { + const float3 cellColor = hash_float_to_float3(cellPosition + cellOffset); + smoothColor = float3::interpolate(smoothColor, cellColor, h) - correctionFactor; + } + if (r_position != nullptr) { + smoothPosition = float4::interpolate(smoothPosition, pointPosition, h) - + correctionFactor; + } + } } } } } - *r_distance = smoothDistance; - *r_color = smoothColor; - *r_position = cellPosition + smoothPosition; + if (r_distance != nullptr) { + *r_distance = smoothDistance; + } + if (r_color != nullptr) { + *r_color = smoothColor; + } + if (r_position != nullptr) { + *r_position = cellPosition + smoothPosition; + } } void voronoi_f2(const float4 coord, @@ -2258,9 +2350,15 @@ void voronoi_f2(const float4 coord, } } } - *r_distance = distanceF2; - *r_color = hash_float_to_float3(cellPosition + offsetF2); - *r_position = positionF2 + cellPosition; + if (r_distance != nullptr) { + *r_distance = distanceF2; + } + if (r_color != nullptr) { + *r_color = hash_float_to_float3(cellPosition + offsetF2); + } + if (r_position != nullptr) { + *r_position = positionF2 + cellPosition; + } } void voronoi_distance_to_edge(const float4 coord, const float randomness, float *r_distance) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc index 574260f3c36..9fcc331e486 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc @@ -239,16 +239,16 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { return params.readonly_single_input(param_index, "Randomness"); }; auto get_r_distance = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Distance"); + return params.uninitialized_single_output_if_required(param_index, "Distance"); }; auto get_r_color = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Color"); + return params.uninitialized_single_output_if_required(param_index, "Color"); }; auto get_r_position = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Position"); + return params.uninitialized_single_output_if_required(param_index, "Position"); }; auto get_r_w = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "W"); + return params.uninitialized_single_output_if_required(param_index, "W"); }; int param = 0; @@ -263,6 +263,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -271,12 +274,16 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -288,6 +295,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -296,12 +306,16 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -314,6 +328,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); @@ -324,12 +341,16 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -346,6 +367,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -353,11 +377,15 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } } break; } @@ -369,6 +397,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -376,11 +407,15 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } } break; } @@ -393,6 +428,9 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); @@ -402,11 +440,15 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { exponent[i], rand, SHD_VORONOI_MINKOWSKI, - &r_distance[i], - &col, - &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } } break; } @@ -425,16 +467,34 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_f1(p, exponent[i], rand, SHD_VORONOI_F1, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_f1(p, + exponent[i], + rand, + SHD_VORONOI_F1, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; } @@ -448,17 +508,34 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_f2( - p, exponent[i], rand, SHD_VORONOI_MINKOWSKI, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_f2(p, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; } @@ -473,18 +550,36 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_smooth_f1( - p, smth, exponent[i], rand, SHD_VORONOI_MINKOWSKI, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_smooth_f1(p, + smth, + exponent[i], + rand, + SHD_VORONOI_MINKOWSKI, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; } @@ -572,16 +667,16 @@ class VoronoiMetricFunction : public fn::MultiFunction { return params.readonly_single_input(param_index, "Randomness"); }; auto get_r_distance = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Distance"); + return params.uninitialized_single_output_if_required(param_index, "Distance"); }; auto get_r_color = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Color"); + return params.uninitialized_single_output_if_required(param_index, "Color"); }; auto get_r_position = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "Position"); + return params.uninitialized_single_output_if_required(param_index, "Position"); }; auto get_r_w = [&](int param_index) -> MutableSpan { - return params.uninitialized_single_output(param_index, "W"); + return params.uninitialized_single_output_if_required(param_index, "W"); }; int param = 0; @@ -595,13 +690,24 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float p = w[i] * scale[i]; const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; - noise::voronoi_f1(p, rand, &r_distance[i], &col, &r_w[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_w[i] = safe_divide(r_w[i], scale[i]); + noise::voronoi_f1(p, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } } break; } @@ -612,13 +718,24 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float p = w[i] * scale[i]; const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; - noise::voronoi_f2(p, rand, &r_distance[i], &col, &r_w[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_w[i] = safe_divide(r_w[i], scale[i]); + noise::voronoi_f2(p, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } } break; } @@ -630,14 +747,26 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float p = w[i] * scale[i]; const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; - noise::voronoi_smooth_f1(p, smth, rand, &r_distance[i], &col, &r_w[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_w[i] = safe_divide(r_w[i], scale[i]); + noise::voronoi_smooth_f1(p, + smth, + rand, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_w ? &r_w[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_w) { + r_w[i] = safe_divide(r_w[i], scale[i]); + } } break; } @@ -653,6 +782,9 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -661,12 +793,16 @@ class VoronoiMetricFunction : public fn::MultiFunction { 0.0f, rand, metric_, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -677,6 +813,9 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; @@ -685,12 +824,16 @@ class VoronoiMetricFunction : public fn::MultiFunction { 0.0f, rand, metric_, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -702,6 +845,9 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); @@ -712,12 +858,16 @@ class VoronoiMetricFunction : public fn::MultiFunction { 0.0f, rand, metric_, - &r_distance[i], - &col, - &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float2::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, 0.0f); + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + pos = float2::safe_divide(pos, scale[i]); + r_position[i] = float3(pos.x, pos.y, 0.0f); + } } break; } @@ -733,13 +883,25 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; - noise::voronoi_f1( - vector[i] * scale[i], 0.0f, rand, metric_, &r_distance[i], &col, &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + noise::voronoi_f1(vector[i] * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } } break; } @@ -750,13 +912,25 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); float3 col; - noise::voronoi_f2( - vector[i] * scale[i], 0.0f, rand, metric_, &r_distance[i], &col, &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + noise::voronoi_f2(vector[i] * scale[i], + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } } break; } @@ -768,21 +942,31 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_distance = get_r_distance(param++); MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); - for (int64_t i : mask) { - const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); - const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); - float3 col; - noise::voronoi_smooth_f1(vector[i] * scale[i], - smth, - 0.0f, - rand, - metric_, - &r_distance[i], - &col, - &r_position[i]); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - r_position[i] = float3::safe_divide(r_position[i], scale[i]); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + { + for (int64_t i : mask) { + const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); + const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); + float3 col; + noise::voronoi_smooth_f1(vector[i] * scale[i], + smth, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position ? &r_position[i] : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position) { + r_position[i] = float3::safe_divide(r_position[i], scale[i]); + } + } } + break; } } @@ -799,16 +983,34 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_f1(p, 0.0f, rand, metric_, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_f1(p, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; } @@ -821,16 +1023,34 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_f2(p, 0.0f, rand, metric_, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_f2(p, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; } @@ -844,17 +1064,36 @@ class VoronoiMetricFunction : public fn::MultiFunction { MutableSpan r_color = get_r_color(param++); MutableSpan r_position = get_r_position(param++); MutableSpan r_w = get_r_w(param++); + const bool calc_distance = !r_distance.is_empty(); + const bool calc_color = !r_color.is_empty(); + const bool calc_position = !r_position.is_empty(); + const bool calc_w = !r_w.is_empty(); for (int64_t i : mask) { const float smth = std::min(std::max(smoothness[i] / 2.0f, 0.0f), 0.5f); const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f); const float4 p = float4(vector[i].x, vector[i].y, vector[i].z, w[i]) * scale[i]; float3 col; float4 pos; - noise::voronoi_smooth_f1(p, smth, 0.0f, rand, metric_, &r_distance[i], &col, &pos); - r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); - pos = float4::safe_divide(pos, scale[i]); - r_position[i] = float3(pos.x, pos.y, pos.z); - r_w[i] = pos.w; + noise::voronoi_smooth_f1(p, + smth, + 0.0f, + rand, + metric_, + calc_distance ? &r_distance[i] : nullptr, + calc_color ? &col : nullptr, + calc_position || calc_w ? &pos : nullptr); + if (calc_color) { + r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f); + } + if (calc_position || calc_w) { + pos = float4::safe_divide(pos, scale[i]); + if (calc_position) { + r_position[i] = float3(pos.x, pos.y, pos.z); + } + if (calc_w) { + r_w[i] = pos.w; + } + } } break; }