Fix #134606: Grease Pencil: Randomization of attributes in primitive tools

Primitive tools were not using the brush randomization options.

This moves the randomization functions into the editor utilities for Grease Pencil
and enables primitive curve generation to use them.

Pull Request: https://projects.blender.org/blender/blender/pulls/135454
This commit is contained in:
Lukas Tönne
2025-03-05 08:49:27 +01:00
parent 8b8b0837a0
commit dc3a652d5b
5 changed files with 388 additions and 178 deletions

View File

@@ -30,6 +30,7 @@ set(SRC
intern/grease_pencil_modes.cc
intern/grease_pencil_ops.cc
intern/grease_pencil_primitive.cc
intern/grease_pencil_randomize.cc
intern/grease_pencil_select.cc
intern/grease_pencil_trim.cc
intern/grease_pencil_undo.cc

View File

@@ -40,6 +40,7 @@
#include "BLI_array_utils.hh"
#include "BLI_math_matrix.hh"
#include "BLI_rand.hh"
#include "BLI_vector.hh"
#include "BLT_translation.hh"
@@ -144,6 +145,14 @@ struct PrimitiveToolOperation {
float4x2 texture_space;
float4x4 local_transform;
RandomNumberGenerator rng;
float stroke_random_radius_factor;
float stroke_random_opacity_factor;
float stroke_random_rotation_factor;
float stroke_random_hue_factor;
float stroke_random_sat_factor;
float stroke_random_val_factor;
OperatorMode mode;
float2 start_position_2d;
int active_control_point_index;
@@ -452,6 +461,7 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
{
const bool on_back = ptd.on_back;
const int new_points_num = grease_pencil_primitive_curve_points_number(ptd);
const bool use_random = (ptd.settings->flag & GP_BRUSH_GROUP_RANDOM) != 0;
bke::CurvesGeometry &curves = ptd.drawing->strokes_for_write();
const int target_curve_index = on_back ? 0 : curves.curves_range().last();
@@ -469,10 +479,22 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
MutableSpan<float> new_radii = ptd.drawing->radii_for_write().slice(curve_points);
MutableSpan<float> new_opacities = ptd.drawing->opacities_for_write().slice(curve_points);
MutableSpan<ColorGeometry4f> new_vertex_colors = ptd.drawing->vertex_colors_for_write().slice(
curve_points);
bke::SpanAttributeWriter<float> rotations;
MutableSpan<float> new_rotations;
if (use_random && ptd.settings->uv_random > 0.0f) {
rotations = curves.attributes_for_write().lookup_or_add_for_write_span<float>(
"rotation", bke::AttrDomain::Point);
new_rotations = rotations.span.slice(curve_points);
}
const ToolSettings *ts = ptd.vc.scene->toolsettings;
const GP_Sculpt_Settings *gset = &ts->gp_sculpt;
/* Screen-space length along curve used as randomization parameter. */
Array<float> lengths(new_points_num);
for (const int point : curve_points.index_range()) {
float pressure = 1.0f;
/* Apply pressure curve. */
@@ -491,15 +513,41 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
const float opacity = ed::greasepencil::opacity_from_input_sample(
pressure, ptd.brush, ptd.settings);
new_radii[point] = radius;
new_opacities[point] = opacity;
}
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (point == 0) {
lengths[point] = 0.0f;
}
else {
const float distance_2d = math::distance(positions_2d[point - 1], positions_2d[point]);
lengths[point] = lengths[point - 1] + distance_2d;
}
new_radii[point] = ed::greasepencil::randomize_radius(
*ptd.settings, ptd.stroke_random_radius_factor, lengths[point], radius, pressure);
new_opacities[point] = ed::greasepencil::randomize_opacity(
*ptd.settings, ptd.stroke_random_opacity_factor, lengths[point], opacity, pressure);
if (ptd.vertex_color) {
new_vertex_colors[point] = ed::greasepencil::randomize_color(*ptd.settings,
ptd.stroke_random_hue_factor,
ptd.stroke_random_sat_factor,
ptd.stroke_random_val_factor,
lengths[point],
*ptd.vertex_color,
pressure);
}
if (rotations) {
new_rotations[point] = ed::greasepencil::randomize_rotation(
*ptd.settings, ptd.stroke_random_rotation_factor, lengths[point], pressure);
}
}
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (ptd.vertex_color) {
ptd.drawing->vertex_colors_for_write().slice(curve_points).fill(*ptd.vertex_color);
point_attributes_to_skip.add("vertex_color");
}
if (rotations) {
point_attributes_to_skip.add("rotation");
rotations.finish();
}
/* Initialize the rest of the attributes with default values. */
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
@@ -764,6 +812,17 @@ static int grease_pencil_primitive_invoke(bContext *C, wmOperator *op, const wmE
ptd.texture_space = ed::greasepencil::calculate_texture_space(
vc.scene, ptd.region, ptd.start_position_2d, ptd.placement);
const bool use_random = (ptd.settings->flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (use_random) {
ptd.rng = RandomNumberGenerator::from_random_seed();
ptd.stroke_random_radius_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_opacity_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_rotation_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_hue_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_sat_factor = ptd.rng.get_float() * 2.0f - 1.0f;
ptd.stroke_random_val_factor = ptd.rng.get_float() * 2.0f - 1.0f;
}
BLI_assert(grease_pencil->has_active_layer());
ptd.local_transform = grease_pencil->get_active_layer()->local_transform();
ptd.drawing = grease_pencil->get_editable_drawing_at(*grease_pencil->get_active_layer(),

View File

@@ -0,0 +1,206 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edgreasepencil
*/
#include "BLI_noise.hh"
#include "BLI_rand.hh"
#include "BKE_colortools.hh"
#include "ED_grease_pencil.hh"
#include "DNA_brush_types.h"
namespace blender::ed::greasepencil {
float randomize_radius(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float radius,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.draw_random_press > 0.0f)) {
return radius;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_pressure, 0, pressure);
}
const float randomized_radius = math::interpolate(
radius, radius * (1.0f + random_factor), settings.draw_random_press);
return math::max(randomized_radius, 0.0f);
}
float randomize_opacity(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float opacity,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.draw_random_strength > 0.0f)) {
return opacity;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_strength, 0, pressure);
}
const float randomized_opacity = math::interpolate(
opacity, opacity + random_factor, settings.draw_random_strength);
return math::clamp(randomized_opacity, 0.0f, 1.0f);
}
float randomize_rotation(const BrushGpencilSettings &settings,
const float stroke_factor,
const float distance,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(float2(distance * noise_scale, stroke_factor));
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings.uv_random);
}
float randomize_rotation(const BrushGpencilSettings &settings,
RandomNumberGenerator &rng,
const float stroke_factor,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
random_factor = rng.get_float() * 2.0f - 1.0f;
}
else {
random_factor = stroke_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings.curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings.uv_random);
}
ColorGeometry4f randomize_color(const BrushGpencilSettings &settings,
const float stroke_hue_factor,
const float stroke_saturation_factor,
const float stroke_value_factor,
const float distance,
const ColorGeometry4f color,
const float pressure)
{
const bool use_random = (settings.flag & GP_BRUSH_GROUP_RANDOM) != 0;
if (!use_random || !(settings.random_hue > 0.0f || settings.random_saturation > 0.0f ||
settings.random_value > 0.0f))
{
return color;
}
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
float random_hue = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
random_hue = noise::perlin_signed(float2(distance * noise_scale, stroke_hue_factor));
}
else {
random_hue = stroke_hue_factor;
}
float random_saturation = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
random_saturation = noise::perlin_signed(
float2(distance * noise_scale, stroke_saturation_factor));
}
else {
random_saturation = stroke_saturation_factor;
}
float random_value = 0.0f;
if ((settings.flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
random_value = noise::perlin_signed(float2(distance * noise_scale, stroke_value_factor));
}
else {
random_value = stroke_value_factor;
}
if ((settings.flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) != 0) {
random_hue *= BKE_curvemapping_evaluateF(settings.curve_rand_hue, 0, pressure);
}
if ((settings.flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) != 0) {
random_saturation *= BKE_curvemapping_evaluateF(settings.curve_rand_saturation, 0, pressure);
}
if ((settings.flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) != 0) {
random_value *= BKE_curvemapping_evaluateF(settings.curve_rand_value, 0, pressure);
}
float3 hsv;
rgb_to_hsv_v(color, hsv);
hsv += float3(random_hue * settings.random_hue,
random_saturation * settings.random_saturation,
random_value * settings.random_value);
/* Wrap hue. */
if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
else if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
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);
random_color.a = color.a;
return random_color;
}
} // namespace blender::ed::greasepencil

View File

@@ -40,12 +40,13 @@ struct BVHTree;
struct GreasePencilLineartModifierData;
struct RV3DMatrixStore;
namespace blender::bke {
namespace blender {
struct RandomNumberGenerator;
namespace bke {
enum class AttrDomain : int8_t;
class CurvesGeometry;
namespace crazyspace {
}
} // namespace blender::bke
} // namespace bke
} // namespace blender
enum {
LAYER_REORDER_ABOVE,
@@ -936,4 +937,65 @@ void add_single_curve(bke::CurvesGeometry &curves, bool at_end);
*/
void resize_single_curve(bke::CurvesGeometry &curves, bool at_end, int new_points_num);
/**
* Calculate a randomized radius value for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param radius Base radius to be randomized.
* \param pressure Pressure factor.
*/
float randomize_radius(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float radius,
float pressure);
/**
* Calculate a randomized opacity value for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param opacity Base opacity to be randomized.
* \param pressure Pressure factor.
*/
float randomize_opacity(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float opacity,
float pressure);
/**
* Calculate a randomized rotation for a point.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param distance Screen-space length in pixels along the curve.
* \param pressure Pressure factor.
*/
float randomize_rotation(const BrushGpencilSettings &settings,
float stroke_factor,
float distance,
float pressure);
/**
* Calculate a randomized rotation for a point.
* \param rng Random number generator instance.
* \param stroke_factor Random seed value in [-1, 1] per stroke.
* \param pressure Pressure factor.
*/
float randomize_rotation(const BrushGpencilSettings &settings,
blender::RandomNumberGenerator &rng,
float stroke_factor,
float pressure);
/**
* Calculate a randomized opacity value for a point.
* \param stroke_hue_factor Random seed value in [-1, 1] per stroke for color hue.
* \param stroke_saturation_factor Random seed value in [-1, 1] per stroke for color saturation.
* \param stroke_value_factor Random seed value in [-1, 1] per stroke for color value.
* \param distance Screen-space length in pixels along the curve.
* \param color Base color to be randomized.
* \param pressure Pressure factor.
*/
ColorGeometry4f randomize_color(const BrushGpencilSettings &settings,
float stroke_hue_factor,
float stroke_saturation_factor,
float stroke_value_factor,
float distance,
ColorGeometry4f color,
float pressure);
} // namespace blender::ed::greasepencil

View File

@@ -257,159 +257,6 @@ struct PaintOperationExecutor {
BLI_assert(drawing_ != nullptr);
}
float randomize_radius(PaintOperation &self,
const float distance,
const float radius,
const float pressure)
{
if (!use_settings_random_ || !(settings_->draw_random_press > 0.0f)) {
return radius;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_radius_factor_));
}
else {
random_factor = self.stroke_random_radius_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_pressure, 0, pressure);
}
const float randomized_radius = math::interpolate(
radius, radius * (1.0f + random_factor), settings_->draw_random_press);
return math::max(randomized_radius, 0.0f);
}
float randomize_opacity(PaintOperation &self,
const float distance,
const float opacity,
const float pressure)
{
if (!use_settings_random_ || !(settings_->draw_random_strength > 0.0f)) {
return opacity;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) {
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
random_factor = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_opacity_factor_));
}
else {
random_factor = self.stroke_random_opacity_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_strength, 0, pressure);
}
const float randomized_opacity = math::interpolate(
opacity, opacity + random_factor, settings_->draw_random_strength);
return math::clamp(randomized_opacity, 0.0f, 1.0f);
}
float randomize_rotation(PaintOperation &self, const float pressure)
{
if (!use_settings_random_ || !(settings_->uv_random > 0.0f)) {
return 0.0f;
}
float random_factor = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) {
random_factor = self.rng_.get_float() * 2.0f - 1.0f;
}
else {
random_factor = self.stroke_random_rotation_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_UV_RAND_PRESS) != 0) {
random_factor *= BKE_curvemapping_evaluateF(settings_->curve_rand_uv, 0, pressure);
}
const float random_rotation = random_factor * math::numbers::pi;
return math::interpolate(0.0f, random_rotation, settings_->uv_random);
}
ColorGeometry4f randomize_color(PaintOperation &self,
const float distance,
const ColorGeometry4f color,
const float pressure)
{
if (!use_settings_random_ ||
!(settings_->random_hue > 0.0f || settings_->random_saturation > 0.0f ||
settings_->random_value > 0.0f))
{
return color;
}
/* TODO: This should be exposed as a setting to scale the noise along the stroke. */
constexpr float noise_scale = 1 / 20.0f;
float random_hue = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) {
random_hue = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_hue_factor_));
}
else {
random_hue = self.stroke_random_hue_factor_;
}
float random_saturation = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) {
random_saturation = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_sat_factor_));
}
else {
random_saturation = self.stroke_random_sat_factor_;
}
float random_value = 0.0f;
if ((settings_->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) {
random_value = noise::perlin_signed(
float2(distance * noise_scale, self.stroke_random_val_factor_));
}
else {
random_value = self.stroke_random_val_factor_;
}
if ((settings_->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) != 0) {
random_hue *= BKE_curvemapping_evaluateF(settings_->curve_rand_hue, 0, pressure);
}
if ((settings_->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) != 0) {
random_saturation *= BKE_curvemapping_evaluateF(
settings_->curve_rand_saturation, 0, pressure);
}
if ((settings_->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) != 0) {
random_value *= BKE_curvemapping_evaluateF(settings_->curve_rand_value, 0, pressure);
}
float3 hsv;
rgb_to_hsv_v(color, hsv);
hsv += float3(random_hue * settings_->random_hue,
random_saturation * settings_->random_saturation,
random_value * settings_->random_value);
/* Wrap hue. */
if (hsv[0] > 1.0f) {
hsv[0] -= 1.0f;
}
else if (hsv[0] < 0.0f) {
hsv[0] += 1.0f;
}
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);
random_color.a = color.a;
return random_color;
}
void process_start_sample(PaintOperation &self,
const bContext &C,
const InputSample &start_sample,
@@ -441,18 +288,30 @@ struct PaintOperationExecutor {
start_location,
self.placement_.to_world_space(),
settings_);
start_radius = randomize_radius(self, 0.0f, start_radius, start_sample.pressure);
start_radius = ed::greasepencil::randomize_radius(
*settings_, self.stroke_random_radius_factor_, 0.0f, start_radius, start_sample.pressure);
float start_opacity = ed::greasepencil::opacity_from_input_sample(
start_sample.pressure, brush_, settings_);
start_opacity = randomize_opacity(self, 0.0f, start_opacity, start_sample.pressure);
start_opacity = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
0.0f,
start_opacity,
start_sample.pressure);
/* Do not allow pressure opacity when drawing tool was invoked temporarily. */
const float fill_opacity = (!self.temp_draw_) ? start_opacity : 1.0f;
const float start_rotation = randomize_rotation(self, start_sample.pressure);
const float start_rotation = ed::greasepencil::randomize_rotation(
*settings_, self.rng_, self.stroke_random_rotation_factor_, start_sample.pressure);
if (use_vertex_color_) {
vertex_color_ = randomize_color(self, 0.0f, vertex_color_, start_sample.pressure);
vertex_color_ = ed::greasepencil::randomize_color(*settings_,
self.stroke_random_hue_factor_,
self.stroke_random_sat_factor_,
self.stroke_random_val_factor_,
0.0f,
vertex_color_,
start_sample.pressure);
}
Scene *scene = CTX_data_scene(&C);
@@ -824,11 +683,18 @@ struct PaintOperationExecutor {
curves.positions_for_write()[last_active_point] = position;
}
if (use_settings_random_ && settings_->draw_random_press > 0.0f) {
radius = randomize_radius(self, self.accum_distance_, radius, extension_sample.pressure);
radius = ed::greasepencil::randomize_radius(*settings_,
self.stroke_random_radius_factor_,
self.accum_distance_,
radius,
extension_sample.pressure);
}
if (use_settings_random_ && settings_->draw_random_strength > 0.0f) {
opacity = randomize_opacity(
self, self.accum_distance_, opacity, extension_sample.pressure);
opacity = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
self.accum_distance_,
opacity,
extension_sample.pressure);
}
drawing_->radii_for_write()[last_active_point] = math::max(radius, prev_radius);
drawing_->opacities_for_write()[last_active_point] = math::max(opacity, prev_opacity);
@@ -871,8 +737,12 @@ struct PaintOperationExecutor {
/* Randomize radii. */
if (use_settings_random_ && settings_->draw_random_press > 0.0f) {
for (const int i : IndexRange(new_points_num)) {
new_radii[i] = randomize_radius(
self, self.accum_distance_ + max_spacing_px * i, radius, extension_sample.pressure);
new_radii[i] = ed::greasepencil::randomize_radius(*settings_,
self.stroke_random_radius_factor_,
self.accum_distance_ +
max_spacing_px * i,
radius,
extension_sample.pressure);
}
}
else {
@@ -882,8 +752,12 @@ struct PaintOperationExecutor {
/* Randomize opacities. */
if (use_settings_random_ && settings_->draw_random_strength > 0.0f) {
for (const int i : IndexRange(new_points_num)) {
new_opacities[i] = randomize_opacity(
self, self.accum_distance_ + max_spacing_px * i, opacity, extension_sample.pressure);
new_opacities[i] = ed::greasepencil::randomize_opacity(*settings_,
self.stroke_random_opacity_factor_,
self.accum_distance_ +
max_spacing_px * i,
opacity,
extension_sample.pressure);
}
}
else {
@@ -897,7 +771,11 @@ struct PaintOperationExecutor {
{
const MutableSpan<float> new_rotations = rotations.span.slice(new_points);
for (const int i : IndexRange(new_points_num)) {
new_rotations[i] = randomize_rotation(self, extension_sample.pressure);
new_rotations[i] = ed::greasepencil::randomize_rotation(
*settings_,
self.rng_,
self.stroke_random_rotation_factor_,
extension_sample.pressure);
}
point_attributes_to_skip.add("rotation");
rotations.finish();
@@ -910,10 +788,14 @@ struct PaintOperationExecutor {
new_points);
if (use_settings_random_ || attributes.contains("vertex_color")) {
for (const int i : IndexRange(new_points_num)) {
new_vertex_colors[i] = randomize_color(self,
self.accum_distance_ + max_spacing_px * i,
vertex_color_,
extension_sample.pressure);
new_vertex_colors[i] = ed::greasepencil::randomize_color(*settings_,
self.stroke_random_hue_factor_,
self.stroke_random_sat_factor_,
self.stroke_random_val_factor_,
self.accum_distance_ +
max_spacing_px * i,
vertex_color_,
extension_sample.pressure);
}
}
else {