From cdccc51b2e71492ec716898681b82e645e9175eb Mon Sep 17 00:00:00 2001 From: Casey Bianco-Davis Date: Fri, 21 Mar 2025 12:15:09 +0100 Subject: [PATCH] Grease Pencil: Draw Tool: Improve random color value and saturation setting results This makes the random vertex color brightness work on a relative basis. Because humans see relative differences in brightness more then absolute brightness, simple adding randomness to `Value` will cause dark colors to be effected more heavily then light colors. This also fixes a problem desaturated colors with becoming red after saturation randomization. Pull Request: https://projects.blender.org/blender/blender/pulls/107315 --- .../intern/grease_pencil_randomize.cc | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_randomize.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_randomize.cc index 16133f9a26a..fb723c25b7e 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_randomize.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_randomize.cc @@ -180,25 +180,41 @@ ColorGeometry4f randomize_color(const BrushGpencilSettings &settings, } float3 hsv; - rgb_to_hsv_v(color, hsv); + linearrgb_to_srgb_v3_v3(hsv, color); + rgb_to_hsv_v(hsv, hsv); - hsv += float3(random_hue * settings.random_hue, - random_saturation * settings.random_saturation, - random_value * settings.random_value); + hsv[0] += random_hue * settings.random_hue; - /* Wrap hue. */ - if (hsv[0] > 1.0f) { - hsv[0] -= 1.0f; - } - else if (hsv[0] < 0.0f) { - hsv[0] += 1.0f; - } + const float absolute_brightness = hsv[2] + random_value * settings.random_value; + /* + * To match relative brightness we want the ratio of the original to modified Value to not + * depend on the brightness of the input Value, Exp is used because we need a function that + * is positive for all 'x' and has the property that 'f(-x) = 1/f(x)' this is so that + * we make the Value on average growth and shrink by the same amount. To detriment the rate + * of the Exponential we set slope to match addition for small random values at an arbitrary + * Base Value. + */ + constexpr float base_value = 0.5f; + const float relative_brightness = hsv[2] * + math::exp(random_value * settings.random_value / base_value); + + /* Use the fourth power. */ + const float blend_factor = math::pow(settings.random_value, 4.0f); + /* Use relative brightness at low randomness, and switch to absolute at high. */ + hsv[2] = math::interpolate(relative_brightness, absolute_brightness, blend_factor); + + /* Multiply by the current saturation to prevent grays from becoming red. */ + hsv[1] += random_saturation * settings.random_saturation * 2.0f * hsv[1]; + + /* Wrap hue, clamp saturation and value. */ + hsv[0] = math::fract(hsv[0]); hsv[1] = math::clamp(hsv[1], 0.0f, 1.0f); hsv[2] = math::clamp(hsv[2], 0.0f, 1.0f); ColorGeometry4f random_color; hsv_to_rgb_v(hsv, random_color); + srgb_to_linearrgb_v3_v3(random_color, random_color); random_color.a = color.a; return random_color; }