Add Fractal Voronoi Noise V.2 #106827

Merged
Jacques Lucke merged 77 commits from Hoshinova/blender:add-fractal-voronoi into main 2023-06-13 09:18:18 +02:00
4 changed files with 343 additions and 166 deletions
Showing only changes of commit 849a80e2f8 - Show all commits

View File

@ -977,14 +977,13 @@ ccl_device void fractal_voronoi_f1(T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
float lerp_amplitude = *max_amplitude + octave_amplitude;
float lerp_distance = *outDistance + octave_distance * octave_amplitude;
float3 lerp_color = *outColor + octave_color * octave_amplitude;
T lerp_position = lerp(*outPosition, octave_postion / octave_scale, octave_amplitude);
*max_amplitude = lerp(*max_amplitude, lerp_amplitude, remainder);
*outDistance = lerp(*outDistance, lerp_distance, remainder);
*outColor = lerp(*outColor, lerp_color, remainder);
*outPosition = lerp(*outPosition, lerp_position, remainder);
*max_amplitude = lerp(*max_amplitude, *max_amplitude + octave_amplitude, remainder);
*outDistance = lerp(
*outDistance, *outDistance + octave_distance * octave_amplitude, remainder);
*outColor = lerp(*outColor, *outColor + octave_color * octave_amplitude, remainder);
*outPosition = lerp(*outPosition,
lerp(*outPosition, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -1039,14 +1038,13 @@ ccl_device void fractal_voronoi_smooth_f1(T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
float lerp_amplitude = *max_amplitude + octave_amplitude;
float lerp_distance = *outDistance + octave_distance * octave_amplitude;
float3 lerp_color = *outColor + octave_color * octave_amplitude;
T lerp_position = lerp(*outPosition, octave_postion / octave_scale, octave_amplitude);
*max_amplitude = lerp(*max_amplitude, lerp_amplitude, remainder);
*outDistance = lerp(*outDistance, lerp_distance, remainder);
*outColor = lerp(*outColor, lerp_color, remainder);
*outPosition = lerp(*outPosition, lerp_position, remainder);
*max_amplitude = lerp(*max_amplitude, *max_amplitude + octave_amplitude, remainder);
*outDistance = lerp(
*outDistance, *outDistance + octave_distance * octave_amplitude, remainder);
*outColor = lerp(*outColor, *outColor + octave_color * octave_amplitude, remainder);
*outPosition = lerp(*outPosition,
lerp(*outPosition, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -1099,14 +1097,13 @@ ccl_device void fractal_voronoi_f2(T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
float lerp_amplitude = *max_amplitude + octave_amplitude;
float lerp_distance = *outDistance + octave_distance * octave_amplitude;
float3 lerp_color = *outColor + octave_color * octave_amplitude;
T lerp_position = lerp(*outPosition, octave_postion / octave_scale, octave_amplitude);
*max_amplitude = lerp(*max_amplitude, lerp_amplitude, remainder);
*outDistance = lerp(*outDistance, lerp_distance, remainder);
*outColor = lerp(*outColor, lerp_color, remainder);
*outPosition = lerp(*outPosition, lerp_position, remainder);
*max_amplitude = lerp(*max_amplitude, *max_amplitude + octave_amplitude, remainder);
*outDistance = lerp(
*outDistance, *outDistance + octave_distance * octave_amplitude, remainder);
*outColor = lerp(*outColor, *outColor + octave_color * octave_amplitude, remainder);
*outPosition = lerp(*outPosition,
lerp(*outPosition, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -1145,9 +1142,9 @@ ccl_device void fractal_voronoi_distance_to_edge(T coord,
if (remainder != 0.0f) {
float lerp_amplitude = lerp(
*max_amplitude, (2.0f - randomness) * octave_scale, octave_amplitude);
*max_amplitude = lerp(*max_amplitude, lerp_amplitude, remainder);
float lerp_distance = lerp(
*outDistance, min(*outDistance, octave_distance / octave_scale), octave_amplitude);
*max_amplitude = lerp(*max_amplitude, lerp_amplitude, remainder);
*outDistance = lerp(*outDistance, min(*outDistance, lerp_distance), remainder);
}
}
@ -1235,7 +1232,7 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
&color_out,
&w_out);
if (normalize) {
/* Optimized std::lerp(max_amplitude * 0.5, max_amplitude, randomness) */
/* Optimized lerp(max_amplitude * 0.5, max_amplitude, randomness) */
distance_out /= (0.5f + 0.5f * randomness) * max_amplitude;
color_out /= max_amplitude;
}
@ -1255,7 +1252,7 @@ ccl_device_noinline int svm_node_tex_voronoi(KernelGlobals kg,
&color_out,
&w_out);
if (normalize) {
/* Optimized std::lerp(max_amplitude * 0.5, max_amplitude, randomness) */
/* Optimized lerp(max_amplitude * 0.5, max_amplitude, randomness) */
distance_out /= (0.5f + 0.5f * randomness) * max_amplitude;
color_out /= max_amplitude;
}

View File

@ -414,7 +414,6 @@ void fractal_voronoi_f1(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -429,7 +428,6 @@ void fractal_voronoi_smooth_f1(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -443,7 +441,6 @@ void fractal_voronoi_f2(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -452,9 +449,10 @@ void fractal_voronoi_f2(const T coord,
template<typename T>
void fractal_voronoi_distance_to_edge(const T coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance);
/** \} */

View File

@ -2369,6 +2369,11 @@ void voronoi_n_sphere_radius(const float4 coord, const float randomness, float *
/* **** Fractal Voronoi **** */
template<class A, class B> static A lerp(const A &a, const A &b, const B &t)
{
return (A)(a * ((B)1 - t) + b * t);
}
template<typename T>
void fractal_voronoi_f1(const T coord,
const float detail,
@ -2377,7 +2382,6 @@ void fractal_voronoi_f1(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2386,28 +2390,44 @@ void fractal_voronoi_f1(const T coord,
float octave_scale = 1.0f;
float octave_amplitude = 1.0f;
float octave_distance = 0.0f;
float3 octave_color{};
T octave_postion{};
*r_max_amplitude = 0.0f;
if (r_distance != nullptr) {
*r_max_amplitude = 0.0f;
*r_distance = 0.0f;
}
for (int i = 0; i <= ceilf(detail); ++i) {
voronoi_f1(
coord * octave_scale, exponent, randomness, metric, &octave_distance, r_color, r_position);
voronoi_f1(coord * octave_scale,
exponent,
randomness,
metric,
&octave_distance,
&octave_color,
&octave_postion);
if (detail == 0.0f || roughness == 0.0f || lacunarity == 0.0f) {
*r_max_amplitude = 1.0f;
if (r_distance != nullptr) {
*r_max_amplitude = max_distance;
*r_distance = octave_distance;
}
if (r_color != nullptr) {
*r_color = octave_color;
}
if (r_position != nullptr) {
*r_position = octave_postion;
}
return;
}
else if (i <= detail) {
*r_max_amplitude += octave_amplitude;
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
*r_distance += octave_distance * octave_amplitude;
}
if (r_color != nullptr) {
*r_color += octave_color * octave_amplitude;
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position, octave_postion / octave_scale, octave_amplitude);
}
octave_scale *= lacunarity;
octave_amplitude *= roughness;
@ -2415,13 +2435,18 @@ void fractal_voronoi_f1(const T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
*r_max_amplitude = lerp(*r_max_amplitude, *r_max_amplitude + octave_amplitude, remainder);
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
float lerp_distance = *r_distance + octave_distance * octave_amplitude;
*r_distance = (1.0f - remainder) * (*r_distance) + remainder * lerp_distance;
*r_distance = lerp(
*r_distance, *r_distance + octave_distance * octave_amplitude, remainder);
}
if (r_color != nullptr) {
*r_color = lerp(*r_color, *r_color + octave_color * octave_amplitude, remainder);
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position,
lerp(*r_position, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -2437,7 +2462,6 @@ void fractal_voronoi_smooth_f1(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2446,9 +2470,11 @@ void fractal_voronoi_smooth_f1(const T coord,
float octave_scale = 1.0f;
float octave_amplitude = 1.0f;
float octave_distance = 0.0f;
float3 octave_color{};
T octave_postion{};
*r_max_amplitude = 0.0f;
if (r_distance != nullptr) {
*r_max_amplitude = 0.0f;
*r_distance = 0.0f;
}
for (int i = 0; i <= ceilf(detail); ++i) {
@ -2458,22 +2484,31 @@ void fractal_voronoi_smooth_f1(const T coord,
randomness,
metric,
&octave_distance,
r_color,
r_position);
&octave_color,
&octave_postion);
if (detail == 0.0f || roughness == 0.0f || lacunarity == 0.0f) {
*r_max_amplitude = 1.0f;
if (r_distance != nullptr) {
*r_max_amplitude = max_distance;
*r_distance = octave_distance;
}
if (r_color != nullptr) {
*r_color = octave_color;
}
if (r_position != nullptr) {
*r_position = octave_postion;
}
return;
}
else if (i <= detail) {
*r_max_amplitude += octave_amplitude;
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
*r_distance += octave_distance * octave_amplitude;
}
if (r_color != nullptr) {
*r_color += octave_color * octave_amplitude;
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position, octave_postion / octave_scale, octave_amplitude);
}
octave_scale *= lacunarity;
octave_amplitude *= roughness;
@ -2481,13 +2516,18 @@ void fractal_voronoi_smooth_f1(const T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
*r_max_amplitude = lerp(*r_max_amplitude, *r_max_amplitude + octave_amplitude, remainder);
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
float lerp_distance = *r_distance + octave_distance * octave_amplitude;
*r_distance = (1.0f - remainder) * (*r_distance) + remainder * lerp_distance;
*r_distance = lerp(
*r_distance, *r_distance + octave_distance * octave_amplitude, remainder);
}
if (r_color != nullptr) {
*r_color = lerp(*r_color, *r_color + octave_color * octave_amplitude, remainder);
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position,
lerp(*r_position, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -2502,7 +2542,6 @@ void fractal_voronoi_f2(const T coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2511,28 +2550,44 @@ void fractal_voronoi_f2(const T coord,
float octave_scale = 1.0f;
float octave_amplitude = 1.0f;
float octave_distance = 0.0f;
float3 octave_color{};
T octave_postion{};
*r_max_amplitude = 0.0f;
if (r_distance != nullptr) {
*r_max_amplitude = 0.0f;
*r_distance = 0.0f;
}
for (int i = 0; i <= ceilf(detail); ++i) {
voronoi_f2(
coord * octave_scale, exponent, randomness, metric, &octave_distance, r_color, r_position);
voronoi_f2(coord * octave_scale,
exponent,
randomness,
metric,
&octave_distance,
&octave_color,
&octave_postion);
if (detail == 0.0f || roughness == 0.0f || lacunarity == 0.0f) {
*r_max_amplitude = 1.0f;
if (r_distance != nullptr) {
*r_max_amplitude = max_distance;
*r_distance = octave_distance;
}
if (r_color != nullptr) {
*r_color = octave_color;
}
if (r_position != nullptr) {
*r_position = octave_postion;
}
return;
}
else if (i <= detail) {
*r_max_amplitude += octave_amplitude;
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
*r_distance += octave_distance * octave_amplitude;
}
if (r_color != nullptr) {
*r_color += octave_color * octave_amplitude;
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position, octave_postion / octave_scale, octave_amplitude);
}
octave_scale *= lacunarity;
octave_amplitude *= roughness;
@ -2540,13 +2595,18 @@ void fractal_voronoi_f2(const T coord,
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
*r_max_amplitude = lerp(*r_max_amplitude, *r_max_amplitude + octave_amplitude, remainder);
if (r_distance != nullptr) {
*r_max_amplitude += max_distance * octave_amplitude;
float lerp_distance = *r_distance + octave_distance * octave_amplitude;
*r_distance = (1.0f - remainder) * (*r_distance) + remainder * lerp_distance;
*r_distance = lerp(
*r_distance, *r_distance + octave_distance * octave_amplitude, remainder);
}
if (r_color != nullptr) {
*r_color = lerp(*r_color, *r_color + octave_color * octave_amplitude, remainder);
}
if (r_position != nullptr) {
*r_position /= octave_scale;
*r_position = lerp(*r_position,
lerp(*r_position, octave_postion / octave_scale, octave_amplitude),
remainder);
}
}
}
@ -2556,22 +2616,43 @@ void fractal_voronoi_f2(const T coord,
template<typename T>
void fractal_voronoi_distance_to_edge(const T coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance)
{
float octave_scale = 1.0f;
float octave_amplitude = 1.0f;
float octave_distance = 0.0f;
*r_max_amplitude = 2.0f - randomness;
*r_distance = 8.0f;
for (int i = 0; i <= ceilf(detail); ++i) {
voronoi_distance_to_edge(coord * octave_scale, randomness, &octave_distance);
*r_distance = std::min(*r_distance, octave_distance / octave_scale);
octave_scale *= lacunarity;
}
if (normalize) {
*r_distance *= (2.0f - randomness) * octave_scale / lacunarity;
if (detail == 0.0f || roughness == 0.0f || lacunarity == 0.0f) {
*r_distance = octave_distance;
return;
}
else if (i <= detail) {
*r_max_amplitude = lerp(
*r_max_amplitude, (2.0f - randomness) * octave_scale, octave_amplitude);
*r_distance = lerp(
*r_distance, std::min(*r_distance, octave_distance / octave_scale), octave_amplitude);
octave_scale *= lacunarity;
octave_amplitude *= roughness;
}
else {
float remainder = detail - floorf(detail);
if (remainder != 0.0f) {
float lerp_amplitude = lerp(
*r_max_amplitude, (2.0f - randomness) * octave_scale, octave_amplitude);
*r_max_amplitude = lerp(*r_max_amplitude, lerp_amplitude, remainder);
float lerp_distance = lerp(
*r_distance, std::min(*r_distance, octave_distance / octave_scale), octave_amplitude);
*r_distance = lerp(*r_distance, std::min(*r_distance, lerp_distance), remainder);
}
}
}
}
@ -2584,7 +2665,6 @@ template void fractal_voronoi_f1<float>(const float coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2596,7 +2676,6 @@ template void fractal_voronoi_f1<float2>(const float2 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2608,7 +2687,6 @@ template void fractal_voronoi_f1<float3>(const float3 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2620,7 +2698,6 @@ template void fractal_voronoi_f1<float4>(const float4 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2634,7 +2711,6 @@ template void fractal_voronoi_smooth_f1<float>(const float coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2647,7 +2723,6 @@ template void fractal_voronoi_smooth_f1<float2>(const float2 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2660,7 +2735,6 @@ template void fractal_voronoi_smooth_f1<float3>(const float3 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2673,7 +2747,6 @@ template void fractal_voronoi_smooth_f1<float4>(const float4 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2686,7 +2759,6 @@ template void fractal_voronoi_f2<float>(const float coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2698,7 +2770,6 @@ template void fractal_voronoi_f2<float2>(const float2 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2710,7 +2781,6 @@ template void fractal_voronoi_f2<float3>(const float3 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2722,7 +2792,6 @@ template void fractal_voronoi_f2<float4>(const float4 coord,
const float exponent,
const float randomness,
const int metric,
const float max_distance,
float *r_max_amplitude,
float *r_distance,
float3 *r_color,
@ -2730,27 +2799,31 @@ template void fractal_voronoi_f2<float4>(const float4 coord,
template void fractal_voronoi_distance_to_edge<float>(const float coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance);
template void fractal_voronoi_distance_to_edge<float2>(const float2 coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance);
template void fractal_voronoi_distance_to_edge<float3>(const float3 coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance);
template void fractal_voronoi_distance_to_edge<float4>(const float4 coord,
const float detail,
const float roughness,
const float lacunarity,
const float randomness,
const bool normalize,
float *r_max_amplitude,
float *r_distance);
/** \} */

View File

@ -291,6 +291,11 @@ static float voronoi_distance(const float4 a,
return 0.0f;
}
template<class A, class B> static A lerp(const A &a, const A &b, const B &t)
{
return (A)(a * ((B)1 - t) + b * t);
}
class VoronoiMetricFunction : public mf::MultiFunction {
private:
int dimensions_;
@ -451,21 +456,26 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
SHD_VORONOI_EUCLIDEAN,
1.0f,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_w ? &r_w[i] : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude, randomness)
*/
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
if (calc_color) {
col /= max_amplitude;
}
}
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]);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -495,25 +505,30 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
SHD_VORONOI_EUCLIDEAN,
1.0f,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_w ? &r_w[i] : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
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]);
}
if (normalize_ && calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) + rand * max_amplitude;
}
}
}
break;
}
@ -546,21 +561,26 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
SHD_VORONOI_EUCLIDEAN,
1.0f,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_w ? &r_w[i] : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude, randomness)
*/
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
if (calc_color) {
col /= max_amplitude;
}
}
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]);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -606,11 +626,24 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude * max_distance;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude * max_distance;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -618,10 +651,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
pos = math::safe_divide(pos, scale[i]);
r_position[i] = float3(pos.x, pos.y, 0.0f);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -662,11 +691,24 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude * max_distance;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude * max_distance;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -674,14 +716,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
pos = math::safe_divide(pos, scale[i]);
r_position[i] = float3(pos.x, pos.y, 0.0f);
}
if (normalize_ && calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) + rand * max_amplitude;
}
}
}
break;
}
@ -725,11 +759,24 @@ class VoronoiMetricFunction : public mf::MultiFunction {
(metric_ == SHD_VORONOI_MINKOWSKI) ? exponent[i] : 0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude * max_distance;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude * max_distance;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -737,10 +784,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
pos = math::safe_divide(pos, scale[i]);
r_position[i] = float3(pos.x, pos.y, 0.0f);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -785,21 +828,26 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &r_position[i] : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude *
* max_distance, randomness) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude * max_distance;
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
if (calc_position) {
r_position[i] = math::safe_divide(r_position[i], scale[i]);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -839,25 +887,30 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &r_position[i] : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude * max_distance;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude * max_distance;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
if (calc_position) {
r_position[i] = math::safe_divide(r_position[i], scale[i]);
}
if (normalize_ && calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) + rand * max_amplitude;
}
}
}
break;
}
@ -901,21 +954,26 @@ class VoronoiMetricFunction : public mf::MultiFunction {
(metric_ == SHD_VORONOI_MINKOWSKI) ? exponent[i] : 0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &r_position[i] : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude *
* max_distance, randomness) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude * max_distance;
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
if (calc_position) {
r_position[i] = math::safe_divide(r_position[i], scale[i]);
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -965,11 +1023,20 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude *
* max_distance, randomness) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude * max_distance;
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -982,10 +1049,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
r_w[i] = pos.w;
}
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -1030,11 +1093,24 @@ class VoronoiMetricFunction : public mf::MultiFunction {
0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude * max_distance;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) +
rand * max_amplitude * max_distance;
}
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -1047,14 +1123,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
r_w[i] = pos.w;
}
}
if (normalize_ && calc_distance) {
if (detail[i] == 0.0f || roughness[i] == 0.0f || lacunarity[i] == 0.0f) {
r_distance[i] /= (1.0f - rand) + rand * max_amplitude;
}
else {
r_distance[i] /= (1.0f - rand) * ceilf(detail[i] + 1.0f) + rand * max_amplitude;
}
}
}
break;
}
@ -1102,11 +1170,20 @@ class VoronoiMetricFunction : public mf::MultiFunction {
(metric_ == SHD_VORONOI_MINKOWSKI) ? exponent[i] : 0.0f,
rand,
metric_,
max_distance,
&max_amplitude,
calc_distance ? &r_distance[i] : nullptr,
calc_color ? &col : nullptr,
calc_position ? &pos : nullptr);
if (normalize_) {
if (calc_distance) {
/* Optimized lerp(max_amplitude * max_distance * 0.5, max_amplitude *
* max_distance, randomness) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude * max_distance;
}
if (calc_color) {
col /= max_amplitude;
}
}
if (calc_color) {
r_color[i] = ColorGeometry4f(col[0], col[1], col[2], 1.0f);
}
@ -1119,10 +1196,6 @@ class VoronoiMetricFunction : public mf::MultiFunction {
r_w[i] = pos.w;
}
}
if (normalize_ && calc_distance) {
/* Optimized std::lerp(max_amplitude*0.5, max_amplitude, rand) */
r_distance[i] /= (0.5f + 0.5f * rand) * max_amplitude;
}
}
break;
}
@ -1237,9 +1310,17 @@ class VoronoiEdgeFunction : public mf::MultiFunction {
for (int64_t i : mask) {
const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f);
const float p = w[i] * scale[i];
float max_amplitude = 0.0f;
noise::fractal_voronoi_distance_to_edge<float>(
p, detail[i], lacunarity[i], rand, normalize_, &r_distance[i]);
p, detail[i], roughness[i], lacunarity[i], rand, &max_amplitude, &r_distance[i]);
if (normalize_) {
/* max_amplitude is used here to keep the code consistent, however it has a
* different meaning than in F1, Smooth F1 and F2. Instead of the highest possible
* amplitude, it represents an abstract factor needed to cancel out the amplitude
* attenuation caused by the higher layers. */
r_distance[i] *= max_amplitude;
}
}
break;
}
@ -1262,15 +1343,24 @@ class VoronoiEdgeFunction : public mf::MultiFunction {
switch (feature_) {
case SHD_VORONOI_DISTANCE_TO_EDGE: {
const VArray<float> &detail = get_detail(param++);
const VArray<float> &roughness = get_roughness(param++);
const VArray<float> &lacunarity = get_lacunarity(param++);
const VArray<float> &randomness = get_randomness(param++);
MutableSpan<float> r_distance = get_r_distance(param++);
for (int64_t i : mask) {
const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f);
const float2 p = float2(vector[i].x, vector[i].y) * scale[i];
float max_amplitude = 0.0f;
noise::fractal_voronoi_distance_to_edge<float2>(
p, detail[i], lacunarity[i], rand, normalize_, &r_distance[i]);
p, detail[i], roughness[i], lacunarity[i], rand, &max_amplitude, &r_distance[i]);
if (normalize_) {
/* max_amplitude is used here to keep the code consistent, however it has a
* different meaning than in F1, Smooth F1 and F2. Instead of the highest possible
* amplitude, it represents an abstract factor needed to cancel out the amplitude
* attenuation caused by the higher layers. */
r_distance[i] *= max_amplitude;
}
}
break;
}
@ -1293,18 +1383,28 @@ class VoronoiEdgeFunction : public mf::MultiFunction {
switch (feature_) {
case SHD_VORONOI_DISTANCE_TO_EDGE: {
const VArray<float> &detail = get_detail(param++);
const VArray<float> &roughness = get_roughness(param++);
const VArray<float> &lacunarity = get_lacunarity(param++);
const VArray<float> &randomness = get_randomness(param++);
MutableSpan<float> r_distance = get_r_distance(param++);
for (int64_t i : mask) {
const float rand = std::min(std::max(randomness[i], 0.0f), 1.0f);
float max_amplitude = 0.0f;
noise::fractal_voronoi_distance_to_edge<float3>(vector[i] * scale[i],
detail[i],
roughness[i],
lacunarity[i],
rand,
normalize_,
&max_amplitude,
&r_distance[i]);
if (normalize_) {
/* max_amplitude is used here to keep the code consistent, however it has a
* different meaning than in F1, Smooth F1 and F2. Instead of the highest possible
* amplitude, it represents an abstract factor needed to cancel out the amplitude
* attenuation caused by the higher layers. */
r_distance[i] *= max_amplitude;
}
}
break;
}
@ -1327,15 +1427,24 @@ class VoronoiEdgeFunction : public mf::MultiFunction {
switch (feature_) {
case SHD_VORONOI_DISTANCE_TO_EDGE: {
const VArray<float> &detail = get_detail(param++);
const VArray<float> &roughness = get_roughness(param++);
const VArray<float> &lacunarity = get_lacunarity(param++);
const VArray<float> &randomness = get_randomness(param++);
MutableSpan<float> r_distance = get_r_distance(param++);
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];
float max_amplitude = 0.0f;
noise::fractal_voronoi_distance_to_edge<float4>(
p, detail[i], lacunarity[i], rand, normalize_, &r_distance[i]);
p, detail[i], roughness[i], lacunarity[i], rand, &max_amplitude, &r_distance[i]);
if (normalize_) {
/* max_amplitude is used here to keep the code consistent, however it has a
* different meaning than in F1, Smooth F1 and F2. Instead of the highest possible
* amplitude, it represents an abstract factor needed to cancel out the amplitude
* attenuation caused by the higher layers. */
r_distance[i] *= max_amplitude;
}
}
break;
}