75 Image *ima_ =
nullptr;
76 ImBuf *ibuf_ =
nullptr;
77 void *lock_ =
nullptr;
84 return ibuf_ !=
nullptr;
97 size_ = {ibuf_->x, ibuf_->y};
99 reinterpret_cast<ColorGeometry4b *
>(ibuf_->byte_buffer.data), ibuf_->x * ibuf_->y);
120 return this->size_.x;
125 return this->size_.y;
130 return c.x >= 0 && c.x < this->size_.x && c.y >= 0 && c.y < this->size_.y;
135 const div_t d = div(index, this->size_.x);
136 return int2{d.rem, d.quot};
141 return c.x + c.y * this->size_.x;
180 const bool is_stroke =
color.r > 0.0f;
181 const bool is_seed =
color.g > 0.0f;
192 constexpr const ColorGeometry4b output_stroke_color = {255, 0, 0, 255};
193 constexpr const ColorGeometry4b output_seed_color = {127, 127, 0, 255};
194 constexpr const ColorGeometry4b output_border_color = {0, 0, 255, 255};
195 constexpr const ColorGeometry4b output_fill_color = {127, 255, 0, 255};
198 constexpr const ColorGeometry4b output_debug_color = {255, 127, 0, 255};
202 std::min(
int(a.
g) +
int(
b.g), 255),
203 std::min(
int(a.
b) +
int(
b.b), 255),
204 std::min(
int(a.
a) +
int(
b.a), 255));
210 output_color = add_colors(output_color, output_debug_color);
213 output_color = add_colors(output_color, output_fill_color);
216 output_color = add_colors(output_color, output_stroke_color);
219 output_color = add_colors(output_color, output_border_color);
222 output_color = add_colors(output_color, output_seed_color);
224 color = std::move(output_color);
236 row_start += buffer.
width();
241 row_start += buffer.
width();
261template<FillBorderMode border_mode>
265 const int width = buffer.
width();
266 const int height = buffer.
height();
272 active_pixels.
push(i);
276 enum FilterDirection {
281 bool border_contact =
false;
283 const int index = active_pixels.
pop();
289 border_contact =
true;
295 border_contact =
true;
315 std::min(width - 1 - coord.x, leak_filter_width));
318 std::min(height - 1 - coord.y, leak_filter_width));
319 bool is_boundary_horizontal =
false;
320 bool is_boundary_vertical =
false;
321 for (
const int filter_i : filter_y_neg) {
325 for (
const int filter_i : filter_y_pos) {
329 for (
const int filter_i : filter_x_neg) {
333 for (
const int filter_i : filter_x_pos) {
339 if (coord.x > 0 && !is_boundary_horizontal) {
342 if (coord.x < width - 1 && !is_boundary_horizontal) {
345 if (coord.y > 0 && !is_boundary_vertical) {
348 if (coord.y < height - 1 && !is_boundary_vertical) {
382 for ([[maybe_unused]]
const int iter :
IndexRange(iterations)) {
395 active_pixels.
push(i);
401 const int index = active_pixels.
pop();
412 for ([[maybe_unused]]
const int iter :
IndexRange(iterations)) {
425 active_pixels.
push(i);
431 const int index = active_pixels.
pop();
457 using BoundarySection = std::list<int>;
461 const int width = buffer.
width();
462 const int height = buffer.
height();
466 constexpr const uint8_t start_direction = 3;
467 auto find_start_coordinates = [&]() -> BoundaryStartMap {
468 BoundaryStartMap starts;
471 for (
const int x :
IndexRange(width).drop_back(1)) {
477 if (!filled_left && filled_right && !border_right) {
479 starts.add(index_right, {});
482 if (!include_holes) {
491 struct NeighborIterator {
497 auto find_next_neighbor = [&](NeighborIterator &iter) ->
bool {
502 const int neighbor_dir =
wrap_dir_3n(iter.direction + 5 + i);
513 iter.index = neighbor_index;
514 iter.direction = neighbor_dir;
521 BoundaryStartMap boundary_starts = find_start_coordinates();
524 for (
const int start_index : boundary_starts.keys()) {
526 if (!boundary_starts.contains(start_index)) {
529 BoundarySection §ion = boundary_starts.lookup(start_index);
530 section.push_back(start_index);
531 NeighborIterator iter = {start_index, start_direction};
532 while (find_next_neighbor(iter)) {
534 if (iter.index == start_index) {
539 if (boundary_starts.contains(iter.index)) {
540 BoundarySection &next_section = boundary_starts.lookup(iter.index);
541 if (next_section.empty()) {
543 boundary_starts.remove(iter.index);
547 section.splice(section.end(), next_section);
548 boundary_starts.remove(iter.index);
553 section.push_back(iter.index);
556 if (iter.index != start_index) {
557 boundary_starts.remove(start_index);
563 for (
const BoundarySection §ion : boundary_starts.values()) {
565 for (
const int index : section) {
571 return final_boundary;
581 const int material_index,
582 const float hardness)
596 "curve_type",
"material_index",
"cyclic",
"hardness",
"fill_opacity"};
600 curves.update_curve_types();
623 cyclic.
span.fill(
true);
624 materials.
span.fill(material_index);
625 hardnesses.span.fill(hardness);
632 fill_opacities.finish();
634 for (
const int point_i :
curves.points_range()) {
635 const int pixel_index = boundary.
pixels[point_i];
638 positions[point_i] = position;
642 constexpr const float pressure = 1.0f;
656 if (use_vertex_color) {
662 skip_curve_attributes.
add(
"fill_color");
666 fill_colors.
span.fill(vertex_color);
670 skip_point_attributes.
add(
"vertex_color");
674 vertex_colors.
span.fill(vertex_color);
700 const int stroke_material_index,
701 const float stroke_hardness,
703 const bool output_as_colors)
705 constexpr const int leak_filter_width = 3;
710 if (output_as_colors) {
741 if (dilate_pixels > 0) {
742 dilate(buffer, dilate_pixels);
744 else if (dilate_pixels < 0) {
745 erode(buffer, -dilate_pixels);
750 const bool fill_holes =
invert;
759 stroke_material_index,
770 const bool is_boundary_layer,
778 auto is_visible_curve = [&](
const int curve_i) {
781 if (points.
size() < 2) {
787 materials[curve_i] + 1);
791 if (gp_style ==
nullptr || is_hidden_material || !is_stroke_material) {
799 if (is_boundary_layer) {
805 if (!is_visible_curve(curve_i)) {
808 const bool is_boundary_stroke = boundary_strokes[curve_i];
809 return is_boundary_stroke;
822 const std::optional<float> alpha_threshold)
824 if (!alpha_threshold) {
830 for (const int curve_i : range) {
831 const Material *material = BKE_object_material_get(const_cast<Object *>(&object),
832 materials[curve_i] + 1);
833 const float material_alpha = material && material->gp_style ?
834 material->gp_style->stroke_rgba[3] :
836 const IndexRange points = curves.points_by_curve()[curve_i];
837 for (const int point_i : points) {
838 const float alpha = (material_alpha * opacities[point_i] > *alpha_threshold ? 1.0f : 0.0f);
839 colors[point_i] = ColorGeometry4f(tint_color.r, tint_color.g, tint_color.b, alpha);
851 return region_bounds;
860 const Object &object_eval,
876 const Layer &layer = *grease_pencil.layers()[info.layer_index];
880 &object_eval,
object, info.layer_index, info.frame_number);
881 const bool only_boundary_strokes = boundary_layers[info.layer_index];
892 object, info, only_boundary_strokes, curve_mask_memory);
897 if (points.
size() < 2) {
901 const int material_index = materials[curve_i];
908 if (only_boundary_strokes && !is_boundary_stroke[curve_i]) {
912 for (
const int point_i : points) {
936 const bool uniform_zoom,
937 const float max_zoom_factor,
943 switch (fit_method) {
962 const float2 fill_bounds_min =
math::min(bounds_min, fill_point) - margin;
963 const float2 fill_bounds_max =
math::max(bounds_max, fill_point) + margin;
964 const float2 fill_bounds_center = 0.5f * (fill_bounds_min + fill_bounds_max);
965 const float2 fill_bounds_extent = fill_bounds_max - fill_bounds_min;
969 const float2 region_center = 0.5f * (region_min + region_max);
970 const float2 region_extent = region_max - region_min;
979 const float2 offset_center = fill_bounds_center - region_center;
980 const float2 offset_min = fill_point + 0.5f * fill_bounds_extent - region_center;
981 const float2 offset_max = fill_point - 0.5f * fill_bounds_extent - region_center;
983 fill_point.x < bounds_min.x ?
985 (fill_point.x > bounds_max.x ? offset_max.x : offset_center.x),
986 fill_point.y < bounds_min.y ?
988 (fill_point.y > bounds_max.y ? offset_max.y : offset_center.y));
991 return std::make_pair(zoom, offset);
1005 const std::optional<float> alpha_threshold,
1006 const float2 &fill_point,
1009 const int stroke_material_index,
1010 const bool keep_images)
1026 const bool uniform_zoom =
true;
1027 const float max_zoom_factor = 5.0f;
1042 constexpr const int min_image_size = 128;
1046 const int2 image_size =
math::max(region_size * pixel_scale,
int2(min_image_size));
1049 const float3 fill_point_layer = placement.
project(fill_point);
1057 if (offscreen_buffer ==
nullptr) {
1061 const bool use_xray =
false;
1065 const float4x4 layer_to_view = world_to_view * layer_to_world;
1073 const float mouse_dot_size = 4.0f;
1077 const Layer &layer = *grease_pencil.layers()[info.layer_index];
1078 if (!layer.is_visible()) {
1082 const bool is_boundary_layer = boundary_layers[info.layer_index];
1091 object, info, is_boundary_layer, curve_mask_memory);
1094 info.drawing.strokes(),
1116 const float line_width = 1.0f;
1137 const float stroke_hardness = 1.0f;
1144 stroke_material_index,
Camera data-block and utility functions.
Low-level operations for curves.
Low-level operations for grease pencil.
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
#define BLI_SCOPED_DEFER(function_to_defer)
void BLI_rctf_union(struct rctf *rct_a, const struct rctf *rct_b)
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
void BLI_rctf_init_pt_radius(struct rctf *rect, const float xy[2], float size)
void BLI_rctf_init_minmax(struct rctf *rect)
#define ENUM_OPERATORS(_type, _max)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
@ GP_MATERIAL_STROKE_SHOW
Object is a sort of wrapper for general info.
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region, const float co[3], float r_co[2], eV3DProjTest flag)
void GPU_blend(eGPUBlend blend)
void GPU_depth_mask(bool depth)
Contains defines and structs used throughout the imbuf module.
BPy_StructRNA * depsgraph
static VArray ForSingle(T value, const int64_t size)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr IndexRange drop_front(int64_t n) const
constexpr IndexRange index_range() const
void push(const T &value)
static VArray ForContainer(ContainerT container)
static VArray ForSingle(T value, const int64_t size)
void append(const T &value)
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
AttributeAccessor attributes() const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
const bke::CurvesGeometry & strokes() const
float4x4 to_world_space(const Object &object) const
float3 project(float2 co) const
float4x4 to_world_space() const
float3 project_with_shift(float2 co) const
MutableSpan< ColorGeometry4b > pixels()
Span< ColorGeometry4b > pixels() const
ColorGeometry4b & pixel_from_coord(const int2 &c)
int2 coord_from_index(const int index) const
int index_from_coord(const int2 &c) const
bool is_valid_coord(const int2 &c) const
const ColorGeometry4b & pixel_from_coord(const int2 &c) const
void foreach_index(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
VecBase< float, 2 > float2
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
GeometryDeformation get_evaluated_grease_pencil_drawing_deformation(const Object *ob_eval, const Object &ob_orig, int layer_index, int frame)
auto attribute_filter_from_skip_ref(const Span< StringRef > skip)
void fill_attribute_range_default(MutableAttributeAccessor dst_attributes, AttrDomain domain, const AttributeFilter &attribute_filter, IndexRange range)
void compute_view_matrices(const ViewContext &view_context, const Scene &scene, const int2 &win_size, const float2 &zoom, const float2 &offset)
void region_reset(ARegion ®ion, const RegionViewData &data)
void draw_lines(const float4x4 &transform, IndexRange indices, Span< float3 > start_positions, Span< float3 > end_positions, const VArray< ColorGeometry4f > &colors, float line_width)
Image * image_render_end(Main &bmain, GPUOffScreen *buffer)
void draw_grease_pencil_strokes(const RegionView3D &rv3d, const int2 &win_size, const Object &object, const bke::greasepencil::Drawing &drawing, const float4x4 &transform, const IndexMask &strokes_mask, const VArray< ColorGeometry4f > &colors, const bool use_xray, const float radius_scale)
RegionViewData region_init(ARegion ®ion, const int2 &win_size)
void draw_dot(const float4x4 &transform, const float3 &position, const float point_size, const ColorGeometry4f &color)
GPUOffScreen * image_render_begin(const int2 &win_size)
void clear_projection_matrix()
void set_projection_matrix(const RegionView3D &rv3d)
static FillBoundary build_fill_boundary(const ImageBufferAccessor &buffer, bool include_holes)
static IndexMask get_visible_boundary_strokes(const Object &object, const DrawingInfo &info, const bool is_boundary_layer, IndexMaskMemory &memory)
static const int2 offset_by_direction[num_directions]
constexpr const char * attr_material_index
static void dilate(ImageBufferAccessor &buffer, int iterations=1)
float opacity_from_input_sample(const float pressure, const Brush *brush, const BrushGpencilSettings *settings)
FillResult flood_fill(ImageBufferAccessor &buffer, const int leak_filter_width=0)
static void erode(ImageBufferAccessor &buffer, int iterations=1)
const ColorGeometry4f draw_boundary_color
static int wrap_dir_3n(const int dir)
bke::CurvesGeometry fill_strokes(const ViewContext &view_context, const Brush &brush, const Scene &scene, const bke::greasepencil::Layer &layer, const VArray< bool > &boundary_layers, Span< DrawingInfo > src_drawings, bool invert, const std::optional< float > alpha_threshold, const float2 &fill_point, const ExtensionData &extensions, FillToolFitMethod fit_method, int stroke_material_index, bool keep_images)
constexpr const int num_directions
float radius_from_input_sample(const RegionView3D *rv3d, const ARegion *region, const Brush *brush, const float pressure, const float3 location, const float4x4 to_world, const BrushGpencilSettings *settings)
static VArray< ColorGeometry4f > get_stroke_colors(const Object &object, const bke::CurvesGeometry &curves, const VArray< float > &opacities, const VArray< int > materials, const ColorGeometry4f &tint_color, const std::optional< float > alpha_threshold)
static void mark_borders(ImageBufferAccessor &buffer)
static rctf get_region_bounds(const ARegion ®ion)
static void convert_colors_to_flags(ImageBufferAccessor &buffer)
static bke::CurvesGeometry boundary_to_curves(const Scene &scene, const ViewContext &view_context, const Brush &brush, const FillBoundary &boundary, const ImageBufferAccessor &buffer, const ed::greasepencil::DrawingPlacement &placement, const int material_index, const float hardness)
constexpr const char * attr_is_boundary
static rctf get_boundary_bounds(const ARegion ®ion, const RegionView3D &rv3d, const Object &object, const Object &object_eval, const VArray< bool > &boundary_layers, const Span< DrawingInfo > src_drawings)
static auto fit_strokes_to_view(const ViewContext &view_context, const VArray< bool > &boundary_layers, const Span< DrawingInfo > src_drawings, const FillToolFitMethod fit_method, const float2 fill_point, const bool uniform_zoom, const float max_zoom_factor, const float2 margin)
static void convert_flags_to_colors(ImageBufferAccessor &buffer)
static void set_flag(ColorGeometry4b &color, const ColorFlag flag, bool value)
const ColorGeometry4f draw_seed_color
static bool get_flag(const ColorGeometry4b &color, const ColorFlag flag)
static void invert_fill(ImageBufferAccessor &buffer)
static bke::CurvesGeometry process_image(Image &ima, const Scene &scene, const ViewContext &view_context, const Brush &brush, const ed::greasepencil::DrawingPlacement &placement, const int stroke_material_index, const float stroke_hardness, const bool invert, const bool output_as_colors)
bool brush_using_vertex_color(const GpPaint *gp_paint, const Brush *brush)
T clamp(const T &a, const T &min, const T &max)
T safe_divide(const T &a, const T &b)
T reduce_max(const VecBase< T, Size > &a)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
MatBase< float, 4, 4 > float4x4
struct BrushGpencilSettings * gpencil_settings
struct MaterialGPencilStyle * gp_style
struct ToolSettings * toolsettings
MutableVArraySpan< T > span
const bke::greasepencil::Drawing & drawing
struct blender::ed::greasepencil::ExtensionData::@205371017122172163221357243254300330236141263101 lines
Vector< int > offset_indices