Fix: GPv3: Draw Tool generates invalid vertex colors

When the drawing contains a stroke that was drawn with vertex colors,
drawing a new stroke with just the material color can lead to invalid
vertex colors.

This was because the draw tool did not write to the vertex color attribute
even if it existed. This meant that when the curves geometry got
resized to be larger, the attribute would contain invalid values for
the new points.

The fix makes sure to write empty vertex colors (black, fully transparent)
to the attribute if the attribute already exists or the vertex color
is being used.

Pull Request: https://projects.blender.org/blender/blender/pulls/124146
This commit is contained in:
Falk David
2024-07-04 15:23:32 +02:00
committed by Falk David
parent 1d2cea1e3e
commit 477897c5c1

View File

@@ -284,10 +284,11 @@ struct PaintOperationExecutor {
Brush *brush_;
BrushGpencilSettings *settings_;
std::optional<ColorGeometry4f> vertex_color_ = std::nullopt;
std::optional<ColorGeometry4f> fill_color_ = std::nullopt;
ColorGeometry4f vertex_color_ = ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f);
ColorGeometry4f fill_color_ = ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f);
float softness_;
bool use_vertex_color_;
bool use_settings_random_;
bke::greasepencil::Drawing *drawing_;
@@ -303,18 +304,17 @@ struct PaintOperationExecutor {
settings_ = brush_->gpencil_settings;
use_settings_random_ = (settings_->flag & GP_BRUSH_GROUP_RANDOM) != 0;
const bool use_vertex_color = (scene_->toolsettings->gp_paint->mode ==
GPPAINT_FLAG_USE_VERTEXCOLOR);
if (use_vertex_color) {
use_vertex_color_ = (scene_->toolsettings->gp_paint->mode == GPPAINT_FLAG_USE_VERTEXCOLOR);
if (use_vertex_color_) {
ColorGeometry4f color_base;
srgb_to_linearrgb_v3_v3(color_base, brush_->rgb);
color_base.a = settings_->vertex_factor;
vertex_color_ = ELEM(settings_->vertex_mode, GPPAINT_MODE_STROKE, GPPAINT_MODE_BOTH) ?
std::make_optional(color_base) :
std::nullopt;
fill_color_ = ELEM(settings_->vertex_mode, GPPAINT_MODE_FILL, GPPAINT_MODE_BOTH) ?
std::make_optional(color_base) :
std::nullopt;
if (ELEM(settings_->vertex_mode, GPPAINT_MODE_STROKE, GPPAINT_MODE_BOTH)) {
vertex_color_ = color_base;
}
if (ELEM(settings_->vertex_mode, GPPAINT_MODE_FILL, GPPAINT_MODE_BOTH)) {
fill_color_ = color_base;
}
}
softness_ = 1.0f - settings_->hardness;
@@ -493,8 +493,8 @@ struct PaintOperationExecutor {
start_opacity = randomize_opacity(self, 0.0f, start_opacity, start_sample.pressure);
const float start_rotation = randomize_rotation(self, start_sample.pressure);
if (vertex_color_) {
vertex_color_.emplace(randomize_color(self, 0.0f, *vertex_color_, start_sample.pressure));
if (use_vertex_color_) {
vertex_color_ = randomize_color(self, 0.0f, vertex_color_, start_sample.pressure);
}
Scene *scene = CTX_data_scene(&C);
@@ -522,12 +522,12 @@ struct PaintOperationExecutor {
drawing_->radii_for_write()[last_active_point] = start_radius;
drawing_->opacities_for_write()[last_active_point] = start_opacity;
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (vertex_color_) {
drawing_->vertex_colors_for_write()[last_active_point] = *vertex_color_;
if (use_vertex_color_ || attributes.contains("vertex_color")) {
drawing_->vertex_colors_for_write()[last_active_point] = vertex_color_;
point_attributes_to_skip.add("vertex_color");
}
if (use_fill && fill_color_) {
drawing_->fill_colors_for_write()[active_curve] = *fill_color_;
if (use_fill || attributes.contains("fill_color")) {
drawing_->fill_colors_for_write()[active_curve] = fill_color_;
curve_attributes_to_skip.add("fill_color");
}
bke::SpanAttributeWriter<float> delta_times = attributes.lookup_or_add_for_write_span<float>(
@@ -879,20 +879,20 @@ struct PaintOperationExecutor {
}
/* Randomize vertex color. */
if (vertex_color_) {
if (use_vertex_color_ || attributes.contains("vertex_color")) {
MutableSpan<ColorGeometry4f> new_vertex_colors = drawing_->vertex_colors_for_write().slice(
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_,
vertex_color_,
extension_sample.pressure);
}
}
else {
linear_interpolation<ColorGeometry4f>(
prev_vertex_color, *vertex_color_, new_vertex_colors, is_first_sample);
prev_vertex_color, vertex_color_, new_vertex_colors, is_first_sample);
}
point_attributes_to_skip.add("vertex_color");
}