From cdf960ececa68af299cb06d7483b65292ab70db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Mon, 27 May 2024 18:24:16 +0200 Subject: [PATCH] GPv3: Use "Precision" setting for the fill tool The Precision setting (aka "fill_factor" in DNA) is used increase or decrease the size of the image buffer for flood fill and thereby balance accuracy vs. performance. This was not yet implemented in GPv3. Pull Request: https://projects.blender.org/blender/blender/pulls/122318 --- .../sculpt_paint/grease_pencil_fill.cc | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/source/blender/editors/sculpt_paint/grease_pencil_fill.cc b/source/blender/editors/sculpt_paint/grease_pencil_fill.cc index 453350488f5..3e225d6126e 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_fill.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_fill.cc @@ -929,13 +929,6 @@ bke::CurvesGeometry fill_strokes(const ViewContext &view_context, GreasePencil &grease_pencil = *static_cast(object.data); const Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object); - // TODO based on the fill_factor (aka "Precision") setting. - constexpr const int min_window_size = 128; - const float pixel_scale = 1.0f; - const int2 win_size = math::max(int2(region.winx, region.winy) * pixel_scale, - int2(min_window_size)); - const float2 win_center = 0.5f * float2(win_size); - /* Zoom and offset based on bounds, to fit all strokes within the render. */ const bool uniform_zoom = true; const float max_zoom_factor = 5.0f; @@ -948,19 +941,35 @@ bke::CurvesGeometry fill_strokes(const ViewContext &view_context, uniform_zoom, max_zoom_factor, margin); - /* Fill point needs to be inverse transformed to stay relative to the view. */ - const float2 fill_point_view = math::safe_divide( - fill_point - win_center - offset * float2(win_size), zoom) + - win_center; /* Scale stroke radius by half to hide gaps between filled areas and boundaries. */ const float radius_scale = 0.5f; - image_render::RegionViewData region_view_data = image_render::region_init(region, win_size); + constexpr const int min_image_size = 128; + /* Pixel scale (aka. "fill_factor, aka. "Precision") to reduce image size. */ + const float pixel_scale = brush.gpencil_settings->fill_factor; + const int2 region_size = int2(region.winx, region.winy); + const int2 image_size = math::max(region_size * pixel_scale, int2(min_image_size)); + + /* Mouse coordinates are in region space, make relative to lower-left view plane corner. */ + const float2 fill_point_image = (math::safe_divide((fill_point - float2(region_size) * 0.5f) - + offset * float2(region_size), + zoom) + + float2(region_size) * 0.5f) * + pixel_scale; + + /* Region size is used for DrawingPlacement projection. */ + image_render::RegionViewData region_view_data = image_render::region_init(region, image_size); + /* Make sure the region is reset on exit. */ + BLI_SCOPED_DEFER([&]() { image_render::region_reset(region, region_view_data); }); + + GPUOffScreen *offscreen_buffer = image_render::image_render_begin(image_size); + if (offscreen_buffer == nullptr) { + return {}; + } - GPUOffScreen *offscreen_buffer = image_render::image_render_begin(win_size); GPU_blend(GPU_BLEND_ALPHA); GPU_depth_mask(true); - image_render::set_viewmat(view_context, scene, win_size, zoom, offset); + image_render::set_viewmat(view_context, scene, image_size, zoom, offset); const eGP_FillDrawModes fill_draw_mode = GP_FILL_DMODE_BOTH; const float alpha_threshold = 0.2f; @@ -970,7 +979,7 @@ bke::CurvesGeometry fill_strokes(const ViewContext &view_context, const float4x4 layer_to_world = layer.to_world_space(object); ed::greasepencil::DrawingPlacement placement(scene, region, view3d, object_eval, &layer); const float3 fill_point_world = math::transform_point(layer_to_world, - placement.project(fill_point_view)); + placement.project(fill_point_image)); /* Draw blue point where click with mouse. */ const float mouse_dot_size = 4.0f; @@ -1002,7 +1011,7 @@ bke::CurvesGeometry fill_strokes(const ViewContext &view_context, brush_fill_hide); image_render::draw_grease_pencil_strokes(rv3d, - win_size, + image_size, object, info.drawing, curve_mask, @@ -1034,11 +1043,6 @@ bke::CurvesGeometry fill_strokes(const ViewContext &view_context, invert, keep_images); - /* Note: Region view reset has to happen after final curve construction, otherwise the curve - * placement, used to re-project from the 2D pixel coordinates, will have the wrong view - * transform. */ - image_render::region_reset(region, region_view_data); - if (!keep_images) { BKE_id_free(view_context.bmain, ima); }