Cleanup: GPv3: Add drawing API for fill color

This adds two functions to the `Drawing` class: `fill_colors()`
and `fill_colors_for_write()`.
In places where the attribute API was used directly, these
functions are now used instead.

This is part of #119080. The point is that developers
shouldn't need to remember the name, type, default value,
and domain of built-in attributes (e.g. used by the renderer).

Pull Request: https://projects.blender.org/blender/blender/pulls/120296
This commit is contained in:
Falk David
2024-04-05 15:28:28 +02:00
committed by Falk David
parent 50c92c29ef
commit d7230516c1
7 changed files with 52 additions and 57 deletions

View File

@@ -79,7 +79,7 @@ class Drawing : public ::GreasePencilDrawing {
/**
* Returns the matrices that transform from a 3D point in layer-space to a 2D point in
* texture-space.
* texture-space. This is stored per curve.
*/
Span<float4x2> texture_matrices() const;
/**
@@ -103,11 +103,19 @@ class Drawing : public ::GreasePencilDrawing {
MutableSpan<float> opacities_for_write();
/**
* Vertex colors of the points. Default is black.
* Vertex colors of the points. Default is black. This is mixed on top of the base material
* stroke color.
*/
VArray<ColorGeometry4f> vertex_colors() const;
MutableSpan<ColorGeometry4f> vertex_colors_for_write();
/**
* Fill colors of the curves. Default is black and fully transparent. This is mixed on top of the
* base material fill color.
*/
VArray<ColorGeometry4f> fill_colors() const;
MutableSpan<ColorGeometry4f> fill_colors_for_write();
/**
* Add a user for this drawing. When a drawing has multiple users, both users are allowed to
* modify this drawings data.

View File

@@ -255,6 +255,7 @@ namespace blender::bke::greasepencil {
static const std::string ATTR_RADIUS = "radius";
static const std::string ATTR_OPACITY = "opacity";
static const std::string ATTR_VERTEX_COLOR = "vertex_color";
static const std::string ATTR_FILL_COLOR = "fill_color";
/* Curves attributes getters */
static int domain_num(const CurvesGeometry &curves, const AttrDomain domain)
@@ -680,6 +681,20 @@ MutableSpan<ColorGeometry4f> Drawing::vertex_colors_for_write()
ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
}
VArray<ColorGeometry4f> Drawing::fill_colors() const
{
return *this->strokes().attributes().lookup_or_default<ColorGeometry4f>(
ATTR_FILL_COLOR, AttrDomain::Curve, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
}
MutableSpan<ColorGeometry4f> Drawing::fill_colors_for_write()
{
return get_mutable_attribute<ColorGeometry4f>(this->strokes_for_write(),
AttrDomain::Curve,
ATTR_FILL_COLOR,
ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
}
void Drawing::tag_texture_matrices_changed()
{
this->runtime->curve_texture_matrices.tag_dirty();

View File

@@ -389,8 +389,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
"delta_time", AttrDomain::Point);
SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
"rotation", AttrDomain::Point);
SpanAttributeWriter<ColorGeometry4f> vertex_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("vertex_color", AttrDomain::Point);
MutableSpan<ColorGeometry4f> vertex_colors = drawing.fill_colors_for_write();
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
".selection", AttrDomain::Point);
MutableSpan<MDeformVert> dverts = use_dverts ? curves.wrap().deform_verts_for_write() :
@@ -410,12 +409,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
"hardness", AttrDomain::Curve);
SpanAttributeWriter<float> stroke_point_aspect_ratios =
attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
SpanAttributeWriter<ColorGeometry4f> stroke_fill_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
"fill_color",
AttrDomain::Curve,
bke::AttributeInitVArray(VArray<ColorGeometry4f>::ForSingle(
ColorGeometry4f(float4(0.0f)), curves.curves_num())));
MutableSpan<ColorGeometry4f> stroke_fill_colors = drawing.fill_colors_for_write();
SpanAttributeWriter<int> stroke_materials = attributes.lookup_or_add_for_write_span<int>(
"material_index", AttrDomain::Curve);
@@ -431,7 +425,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_hardnesses.span[stroke_i] = gps->hardness;
stroke_point_aspect_ratios.span[stroke_i] = gps->aspect_ratio[0] /
max_ff(gps->aspect_ratio[1], 1e-8);
stroke_fill_colors.span[stroke_i] = ColorGeometry4f(gps->vert_color_fill);
stroke_fill_colors[stroke_i] = ColorGeometry4f(gps->vert_color_fill);
stroke_materials.span[stroke_i] = gps->mat_nr;
IndexRange points = points_by_curve[stroke_i];
@@ -458,7 +452,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
MutableSpan<float> dst_opacities = opacities.slice(points);
MutableSpan<float> dst_deltatimes = delta_times.span.slice(points);
MutableSpan<float> dst_rotations = rotations.span.slice(points);
MutableSpan<ColorGeometry4f> dst_vertex_colors = vertex_colors.span.slice(points);
MutableSpan<ColorGeometry4f> dst_vertex_colors = vertex_colors.slice(points);
MutableSpan<bool> dst_selection = selection.span.slice(points);
MutableSpan<MDeformVert> dst_dverts = use_dverts ? dverts.slice(points) :
MutableSpan<MDeformVert>();
@@ -526,7 +520,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
delta_times.finish();
rotations.finish();
vertex_colors.finish();
selection.finish();
stroke_cyclic.finish();
@@ -535,7 +528,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_end_caps.finish();
stroke_hardnesses.finish();
stroke_point_aspect_ratios.finish();
stroke_fill_colors.finish();
stroke_materials.finish();
}

View File

@@ -533,9 +533,7 @@ static void grease_pencil_geom_batch_ensure(Object &object,
"hardness", bke::AttrDomain::Curve, 1.0f);
const VArray<float> stroke_point_aspect_ratios = *attributes.lookup_or_default<float>(
"aspect_ratio", bke::AttrDomain::Curve, 1.0f);
const VArray<ColorGeometry4f> stroke_fill_colors =
*attributes.lookup_or_default<ColorGeometry4f>(
"fill_color", bke::AttrDomain::Curve, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
const VArray<ColorGeometry4f> stroke_fill_colors = info.drawing.fill_colors();
const VArray<int> materials = *attributes.lookup_or_default<int>(
"material_index", bke::AttrDomain::Curve, 0);
const VArray<float> u_translations = *attributes.lookup_or_default<float>(

View File

@@ -166,13 +166,7 @@ void TintOperation::execute_tint(const bContext &C, const InputSample &extension
bke::CurvesGeometry &strokes = drawing.strokes_for_write();
MutableSpan<ColorGeometry4f> vertex_colors = drawing.vertex_colors_for_write();
bke::MutableAttributeAccessor stroke_attributes = strokes.attributes_for_write();
bke::SpanAttributeWriter<ColorGeometry4f> fill_colors =
stroke_attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
"fill_color",
bke::AttrDomain::Curve,
bke::AttributeInitVArray(VArray<ColorGeometry4f>::ForSingle(
ColorGeometry4f(float4(0.0f)), strokes.curves_num())));
MutableSpan<ColorGeometry4f> fill_colors = drawing.fill_colors_for_write();
OffsetIndices<int> points_by_curve = strokes.points_by_curve();
const Span<float2> screen_space_positions =
@@ -215,7 +209,7 @@ void TintOperation::execute_tint(const bContext &C, const InputSample &extension
}
}
}
if (tint_fills && !fill_colors.span.is_empty()) {
if (tint_fills && !fill_colors.is_empty()) {
/* Will tint fill color when either the brush being inside the fill region or touching
* the stroke. */
const bool fill_effective = stroke_touched ||
@@ -225,12 +219,12 @@ void TintOperation::execute_tint(const bContext &C, const InputSample &extension
mouse_position);
if (fill_effective) {
float4 premultiplied;
straight_to_premul_v4_v4(premultiplied, fill_colors.span[curve]);
straight_to_premul_v4_v4(premultiplied, fill_colors[curve]);
float4 rgba = float4(
math::interpolate(float3(premultiplied), float3(color_), fill_strength),
fill_colors.span[curve][3]);
fill_colors[curve][3]);
rgba[3] = rgba[3] * (1.0f - fill_strength) + fill_strength;
premul_to_straight_v4_v4(fill_colors.span[curve], rgba);
premul_to_straight_v4_v4(fill_colors[curve], rgba);
stroke_touched = true;
}
}
@@ -239,7 +233,6 @@ void TintOperation::execute_tint(const bContext &C, const InputSample &extension
}
}
});
fill_colors.finish();
};
threading::parallel_for_each(drawings_, [&](const MutableDrawingInfo &info) {

View File

@@ -136,14 +136,13 @@ static void modify_stroke_color(Object &ob,
static void modify_fill_color(Object &ob,
const GreasePencilColorModifierData &cmd,
bke::CurvesGeometry &curves,
Drawing &drawing,
const IndexMask &curves_mask)
{
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
const bke::CurvesGeometry &curves = drawing.strokes();
const bke::AttributeAccessor attributes = curves.attributes();
/* Fill color per stroke. */
bke::SpanAttributeWriter<ColorGeometry4f> fill_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("fill_color",
bke::AttrDomain::Curve);
MutableSpan<ColorGeometry4f> fill_colors = drawing.fill_colors_for_write();
const VArray<int> stroke_materials = *attributes.lookup_or_default<int>(
"material_index", bke::AttrDomain::Curve, 0);
@@ -153,10 +152,8 @@ static void modify_fill_color(Object &ob,
const ColorGeometry4f material_color = (gp_style ? ColorGeometry4f(gp_style->fill_rgba) :
ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
apply_color_factor(fill_colors.span[curve_i], material_color, cmd.hsv);
apply_color_factor(fill_colors[curve_i], material_color, cmd.hsv);
});
fill_colors.finish();
}
static void modify_drawing(ModifierData &md, const ModifierEvalContext &ctx, Drawing &drawing)
@@ -174,12 +171,12 @@ static void modify_drawing(ModifierData &md, const ModifierEvalContext &ctx, Dra
*ctx.object, cmd, curves, curves_mask, drawing.vertex_colors_for_write());
break;
case MOD_GREASE_PENCIL_COLOR_FILL:
modify_fill_color(*ctx.object, cmd, curves, curves_mask);
modify_fill_color(*ctx.object, cmd, drawing, curves_mask);
break;
case MOD_GREASE_PENCIL_COLOR_BOTH:
modify_stroke_color(
*ctx.object, cmd, curves, curves_mask, drawing.vertex_colors_for_write());
modify_fill_color(*ctx.object, cmd, curves, curves_mask);
modify_fill_color(*ctx.object, cmd, drawing, curves_mask);
break;
case MOD_GREASE_PENCIL_COLOR_HARDNESS:
BLI_assert_unreachable();

View File

@@ -239,12 +239,13 @@ static void modify_stroke_color(Object &ob,
static void modify_fill_color(Object &ob,
const GreasePencilTintModifierData &tmd,
bke::CurvesGeometry &curves,
Drawing &drawing,
const IndexMask &curves_mask)
{
const bool use_weight_as_factor = (tmd.flag & MOD_GREASE_PENCIL_TINT_USE_WEIGHT_AS_FACTOR);
const bool invert_vertex_group = (tmd.influence.flag &
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
const bke::CurvesGeometry &curves = drawing.strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const GreasePencilTintModifierMode tint_mode = GreasePencilTintModifierMode(tmd.tint_mode);
@@ -253,14 +254,9 @@ static void modify_fill_color(Object &ob,
return;
}
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
bke::MutableAttributeAccessor attributes = drawing.strokes_for_write().attributes_for_write();
/* Fill color per stroke. */
bke::SpanAttributeWriter<ColorGeometry4f> fill_colors =
attributes.lookup_or_add_for_write_span<ColorGeometry4f>(
"fill_color",
bke::AttrDomain::Curve,
bke::AttributeInitVArray(VArray<ColorGeometry4f>::ForSingle(
ColorGeometry4f(float4(0.0f)), curves.curves_num())));
MutableSpan<ColorGeometry4f> fill_colors = drawing.fill_colors_for_write();
const VArray<int> stroke_materials = *attributes.lookup_or_default<int>(
"material_index", bke::AttrDomain::Curve, 0);
const VArray<float> vgroup_weights = modifier::greasepencil::get_influence_vertex_weights(
@@ -288,10 +284,8 @@ static void modify_fill_color(Object &ob,
case MOD_GREASE_PENCIL_TINT_UNIFORM: {
curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
const ColorGeometry4f material_color = get_material_color(curve_i);
fill_colors.span[curve_i] = apply_uniform_tint(
tmd,
get_base_color(fill_colors.span[curve_i], material_color),
get_curve_factor(curve_i));
fill_colors[curve_i] = apply_uniform_tint(
tmd, get_base_color(fill_colors[curve_i], material_color), get_curve_factor(curve_i));
});
break;
}
@@ -308,18 +302,16 @@ static void modify_fill_color(Object &ob,
const float3 pos = points.is_empty() ? float3(0.0f, 0.0f, 0.0f) :
positions[points.first()];
fill_colors.span[curve_i] = apply_gradient_tint(
fill_colors[curve_i] = apply_gradient_tint(
tmd,
matrix,
pos,
get_base_color(fill_colors.span[curve_i], material_color),
get_base_color(fill_colors[curve_i], material_color),
get_curve_factor(curve_i));
});
break;
}
}
fill_colors.finish();
}
static void modify_opacity(const GreasePencilTintModifierData &tmd,
@@ -365,12 +357,12 @@ static void modify_curves(ModifierData &md, const ModifierEvalContext &ctx, Draw
*ctx.object, tmd, curves, curves_mask, drawing.vertex_colors_for_write());
break;
case MOD_GREASE_PENCIL_COLOR_FILL:
modify_fill_color(*ctx.object, tmd, curves, curves_mask);
modify_fill_color(*ctx.object, tmd, drawing, curves_mask);
break;
case MOD_GREASE_PENCIL_COLOR_BOTH:
modify_stroke_color(
*ctx.object, tmd, curves, curves_mask, drawing.vertex_colors_for_write());
modify_fill_color(*ctx.object, tmd, curves, curves_mask);
modify_fill_color(*ctx.object, tmd, drawing, curves_mask);
break;
case MOD_GREASE_PENCIL_COLOR_HARDNESS:
BLI_assert_unreachable();