GPv3: Weight Paint tools (Draw, Blur, Average, Smear, Sample weight) #118347
|
@ -188,8 +188,17 @@ static void OVERLAY_cache_init(void *vedata)
|
|||
case CTX_MODE_PARTICLE:
|
||||
OVERLAY_edit_particle_cache_init(data);
|
||||
break;
|
||||
case CTX_MODE_PAINT_WEIGHT: {
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
if (draw_ctx->obact != nullptr && draw_ctx->obact->type == OB_GREASE_PENCIL) {
|
||||
OVERLAY_edit_grease_pencil_cache_init(data);
|
||||
}
|
||||
else {
|
||||
OVERLAY_paint_cache_init(data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CTX_MODE_POSE:
|
||||
case CTX_MODE_PAINT_WEIGHT:
|
||||
case CTX_MODE_PAINT_VERTEX:
|
||||
case CTX_MODE_PAINT_TEXTURE:
|
||||
OVERLAY_paint_cache_init(data);
|
||||
|
@ -750,6 +759,7 @@ static void OVERLAY_draw_scene(void *vedata)
|
|||
OVERLAY_edit_curves_draw(data);
|
||||
break;
|
||||
case CTX_MODE_EDIT_GREASE_PENCIL:
|
||||
case CTX_MODE_PAINT_WEIGHT:
|
||||
OVERLAY_edit_grease_pencil_draw(data);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -24,6 +24,7 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
|
|||
const bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(
|
||||
draw_ctx->scene->toolsettings);
|
||||
const View3D *v3d = draw_ctx->v3d;
|
||||
const bool in_weight_paint_mode = (draw_ctx->object_mode == OB_MODE_WEIGHT_PAINT);
|
||||
|
||||
GPUShader *sh;
|
||||
DRWShadingGroup *grp;
|
||||
|
@ -32,7 +33,7 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
|
|||
DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->edit_grease_pencil_ps, (state | pd->clipping_state));
|
||||
|
||||
const bool show_points = selection_domain == bke::AttrDomain::Point;
|
||||
const bool show_points = (selection_domain == bke::AttrDomain::Point) || in_weight_paint_mode;
|
||||
const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) != 0;
|
||||
|
||||
if (show_lines) {
|
||||
|
@ -45,6 +46,11 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
|
|||
sh = OVERLAY_shader_edit_particle_point();
|
||||
grp = pd->edit_grease_pencil_points_grp = DRW_shgroup_create(sh, psl->edit_grease_pencil_ps);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
|
||||
/* TODO: this naive attempt to show vertex weights using a color ramp does not work yet... */
|
||||
if (in_weight_paint_mode) {
|
||||
DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,6 +74,26 @@ void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
}
|
||||
}
|
||||
|
||||
void OVERLAY_weight_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
OVERLAY_PrivateData *pd = vedata->stl->pd;
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
|
||||
DRWShadingGroup *lines_grp = pd->edit_grease_pencil_wires_grp;
|
||||
if (lines_grp) {
|
||||
GPUBatch *geom_lines = DRW_cache_grease_pencil_weight_lines_get(draw_ctx->scene, ob);
|
||||
|
||||
DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
|
||||
}
|
||||
|
||||
DRWShadingGroup *points_grp = pd->edit_grease_pencil_points_grp;
|
||||
if (points_grp) {
|
||||
GPUBatch *geom_points = DRW_cache_grease_pencil_weight_points_get(draw_ctx->scene, ob);
|
||||
DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
|
||||
}
|
||||
}
|
||||
|
||||
void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata)
|
||||
{
|
||||
OVERLAY_PassList *psl = vedata->psl;
|
||||
|
|
|
@ -254,7 +254,7 @@ void OVERLAY_paint_weight_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
|||
OVERLAY_paint_vertex_cache_populate(vedata, ob);
|
||||
break;
|
||||
case OB_GREASE_PENCIL:
|
||||
/* TODO */
|
||||
OVERLAY_weight_grease_pencil_cache_populate(vedata, ob);
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
|
|
|
@ -560,6 +560,7 @@ void OVERLAY_edit_gpencil_legacy_draw(OVERLAY_Data *vedata);
|
|||
|
||||
void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata);
|
||||
void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
|
||||
void OVERLAY_weight_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob);
|
||||
void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata);
|
||||
|
||||
void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata);
|
||||
|
|
|
@ -280,4 +280,6 @@ GPUBatch *DRW_cache_grease_pencil_edit_points_get(const Scene *scene, Object *ob
|
|||
GPUBatch *DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *ob);
|
||||
GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Object *ob);
|
||||
GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object *ob);
|
||||
GPUBatch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob);
|
||||
GPUBatch *DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object *ob);
|
||||
} // namespace blender::draw
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_grease_pencil.h"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
|
||||
|
@ -209,6 +210,197 @@ static void copy_transformed_positions(const Span<float3> src_positions,
|
|||
}
|
||||
}
|
||||
|
||||
static void grease_pencil_weight_batch_ensure(Object &object,
|
||||
const GreasePencil &grease_pencil,
|
||||
const Scene &scene)
|
||||
{
|
||||
using namespace blender::bke::greasepencil;
|
||||
|
||||
constexpr float no_active_weight = -1.0f;
|
||||
|
||||
BLI_assert(grease_pencil.runtime != nullptr);
|
||||
GreasePencilBatchCache *cache = static_cast<GreasePencilBatchCache *>(
|
||||
grease_pencil.runtime->batch_cache);
|
||||
|
||||
if (cache->edit_points_pos != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Should be discarded together. */
|
||||
BLI_assert(cache->edit_points_pos == nullptr && cache->edit_line_indices == nullptr &&
|
||||
cache->edit_points_indices == nullptr);
|
||||
BLI_assert(cache->edit_points == nullptr && cache->edit_lines == nullptr);
|
||||
|
||||
/* Get active vertex group. */
|
||||
const bDeformGroup *active_defgroup = static_cast<bDeformGroup *>(BLI_findlink(
|
||||
&grease_pencil.vertex_group_names, grease_pencil.vertex_group_active_index - 1));
|
||||
if (active_defgroup == nullptr) {
|
||||
return;
|
||||
}
|
||||
const char *active_defgroup_name = active_defgroup->name;
|
||||
|
||||
/* Get the visible drawings. */
|
||||
const Array<ed::greasepencil::DrawingInfo> drawings =
|
||||
ed::greasepencil::retrieve_visible_drawings(scene, grease_pencil);
|
||||
|
||||
const Span<const Layer *> layers = grease_pencil.layers();
|
||||
|
||||
static GPUVertFormat format_points_pos = {0};
|
||||
if (format_points_pos.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format_points_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
static GPUVertFormat format_points_weight = {0};
|
||||
if (format_points_weight.attr_len == 0) {
|
||||
/* TODO: use something like "weight" as attribute name. */
|
||||
GPU_vertformat_attr_add(&format_points_weight, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
|
||||
cache->edit_points_pos = GPU_vertbuf_create_with_format_ex(&format_points_pos, vbo_flag);
|
||||
cache->edit_points_selection = GPU_vertbuf_create_with_format_ex(&format_points_weight,
|
||||
vbo_flag);
|
||||
|
||||
int visible_points_num = 0;
|
||||
int total_line_ids_num = 0;
|
||||
int total_points_num = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
total_points_num += curves.points_num();
|
||||
}
|
||||
|
||||
GPU_vertbuf_data_alloc(cache->edit_points_pos, total_points_num);
|
||||
GPU_vertbuf_data_alloc(cache->edit_points_selection, total_points_num);
|
||||
|
||||
MutableSpan<float3> points_pos = {
|
||||
static_cast<float3 *>(GPU_vertbuf_get_data(cache->edit_points_pos)),
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos)};
|
||||
MutableSpan<float> points_weight = {
|
||||
static_cast<float *>(GPU_vertbuf_get_data(cache->edit_points_selection)),
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_selection)};
|
||||
|
||||
int drawing_start_offset = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const Layer &layer = *layers[info.layer_index];
|
||||
const float4x4 layer_space_to_object_space = layer.to_object_space(object);
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||
object, info.drawing, memory);
|
||||
|
||||
const IndexRange points(drawing_start_offset, curves.points_num());
|
||||
const Span<float3> positions = curves.positions();
|
||||
MutableSpan<float3> positions_slice = points_pos.slice(points);
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange range) {
|
||||
copy_transformed_positions(positions, range, layer_space_to_object_space, positions_slice);
|
||||
});
|
||||
|
||||
/* Get vertex weights of the active vertex group in this drawing. */
|
||||
const int def_nr = BLI_findstringindex(
|
||||
&curves.vertex_group_names, active_defgroup_name, offsetof(bDeformGroup, name));
|
||||
const Span<MDeformVert> dverts = curves.deform_verts();
|
||||
const VArray<float> weights = (def_nr < 0 || layer.is_locked()) ?
|
||||
VArray<float>::ForSingle(no_active_weight,
|
||||
curves.points_num()) :
|
||||
bke::varray_for_deform_verts(dverts, def_nr);
|
||||
MutableSpan<float> weights_slice = points_weight.slice(points);
|
||||
weights.materialize(weights_slice);
|
||||
|
||||
drawing_start_offset += curves.points_num();
|
||||
|
||||
/* Add one id for the restart after every curve. */
|
||||
total_line_ids_num += visible_strokes.size();
|
||||
Array<int> size_per_editable_stroke(visible_strokes.size());
|
||||
offset_indices::gather_group_sizes(points_by_curve, visible_strokes, size_per_editable_stroke);
|
||||
/* Add one id for every non-cyclic segment. */
|
||||
total_line_ids_num += std::accumulate(
|
||||
size_per_editable_stroke.begin(), size_per_editable_stroke.end(), 0);
|
||||
/* Add one id for the last segment of every cyclic curve. */
|
||||
total_line_ids_num += array_utils::count_booleans(curves.cyclic(), visible_strokes);
|
||||
|
||||
/* Do not show weights for locked layers. */
|
||||
if (layer.is_locked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visible_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
visible_points_num += points.size();
|
||||
});
|
||||
}
|
||||
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init_ex(&elb,
|
||||
GPU_PRIM_LINE_STRIP,
|
||||
total_line_ids_num,
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos));
|
||||
|
||||
GPUIndexBufBuilder epb;
|
||||
GPU_indexbuf_init_ex(&epb,
|
||||
GPU_PRIM_POINTS,
|
||||
visible_points_num,
|
||||
GPU_vertbuf_get_vertex_len(cache->edit_points_pos));
|
||||
|
||||
/* Fill point index buffer with data. */
|
||||
drawing_start_offset = 0;
|
||||
for (const ed::greasepencil::DrawingInfo &info : drawings) {
|
||||
const Layer *layer = layers[info.layer_index];
|
||||
const bke::CurvesGeometry &curves = info.drawing.strokes();
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask editable_strokes = ed::greasepencil::retrieve_editable_strokes(
|
||||
object, info.drawing, memory);
|
||||
|
||||
/* Fill line indices. */
|
||||
editable_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const bool is_cyclic = cyclic[curve_i];
|
||||
|
||||
for (const int point_i : points) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, point_i + drawing_start_offset);
|
||||
}
|
||||
|
||||
if (is_cyclic) {
|
||||
GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset);
|
||||
}
|
||||
|
||||
GPU_indexbuf_add_primitive_restart(&elb);
|
||||
});
|
||||
|
||||
/* Fill point indices. */
|
||||
if (!layer->is_locked()) {
|
||||
editable_strokes.foreach_index([&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
for (const int point : points) {
|
||||
GPU_indexbuf_add_generic_vert(&epb, point + drawing_start_offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
drawing_start_offset += curves.points_num();
|
||||
}
|
||||
|
||||
cache->edit_line_indices = GPU_indexbuf_build(&elb);
|
||||
cache->edit_points_indices = GPU_indexbuf_build(&epb);
|
||||
|
||||
/* Create the batches. */
|
||||
cache->edit_points = GPU_batch_create(
|
||||
GPU_PRIM_POINTS, cache->edit_points_pos, cache->edit_points_indices);
|
||||
GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_selection, false);
|
||||
|
||||
cache->edit_lines = GPU_batch_create(
|
||||
GPU_PRIM_LINE_STRIP, cache->edit_points_pos, cache->edit_line_indices);
|
||||
|
||||
/* Allow creation of buffer texture. */
|
||||
GPU_vertbuf_use(cache->edit_points_pos);
|
||||
GPU_vertbuf_use(cache->edit_points_selection);
|
||||
|
||||
cache->is_dirty = false;
|
||||
}
|
||||
|
||||
static void grease_pencil_edit_batch_ensure(Object &object,
|
||||
const GreasePencil &grease_pencil,
|
||||
const Scene &scene)
|
||||
|
@ -736,4 +928,22 @@ GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object
|
|||
return cache->vbo_col;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob)
|
||||
{
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
|
||||
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
|
||||
grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene);
|
||||
|
||||
return cache->edit_points;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object *ob)
|
||||
{
|
||||
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
|
||||
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
|
||||
grease_pencil_weight_batch_ensure(*ob, grease_pencil, *scene);
|
||||
|
||||
return cache->edit_lines;
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
|
|
Loading…
Reference in New Issue