diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index b5f018a5f09..720b9a59e95 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -209,7 +209,8 @@ set(SRC engines/overlay/overlay_extra.cc engines/overlay/overlay_facing.cc engines/overlay/overlay_fade.cc - engines/overlay/overlay_gpencil.cc + engines/overlay/overlay_gpencil_legacy.cc + engines/overlay/overlay_grease_pencil.cc engines/overlay/overlay_grid.cc engines/overlay/overlay_image.cc engines/overlay/overlay_lattice.cc diff --git a/source/blender/draw/engines/overlay/overlay_engine.cc b/source/blender/draw/engines/overlay/overlay_engine.cc index f10813003cd..3075c9b1317 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.cc +++ b/source/blender/draw/engines/overlay/overlay_engine.cc @@ -194,11 +194,18 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_sculpt_cache_init(data); break; case CTX_MODE_EDIT_GPENCIL: + if (U.experimental.use_grease_pencil_version3) { + OVERLAY_edit_grease_pencil_cache_init(data); + } + else { + OVERLAY_edit_gpencil_legacy_cache_init(data); + } + break; case CTX_MODE_PAINT_GPENCIL: case CTX_MODE_SCULPT_GPENCIL: case CTX_MODE_VERTEX_GPENCIL: case CTX_MODE_WEIGHT_GPENCIL: - OVERLAY_edit_gpencil_cache_init(data); + OVERLAY_edit_gpencil_legacy_cache_init(data); break; case CTX_MODE_EDIT_CURVES: OVERLAY_edit_curves_cache_init(data); @@ -220,7 +227,7 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_mode_transfer_cache_init(data); OVERLAY_extra_cache_init(data); OVERLAY_facing_cache_init(data); - OVERLAY_gpencil_cache_init(data); + OVERLAY_gpencil_legacy_cache_init(data); OVERLAY_grid_cache_init(data); OVERLAY_image_cache_init(data); OVERLAY_metaball_cache_init(data); @@ -279,6 +286,8 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj case OB_VOLUME: /* No edit mode yet. */ return false; + case OB_GREASE_PENCIL: + return pd->ctx_mode == CTX_MODE_EDIT_GPENCIL; } } return false; @@ -430,6 +439,11 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) case OB_CURVES: OVERLAY_edit_curves_cache_populate(data, ob); break; + case OB_GREASE_PENCIL: + if (U.experimental.use_grease_pencil_version3) { + OVERLAY_edit_grease_pencil_cache_populate(data, ob); + } + break; } } else if (in_pose_mode && draw_bones) { @@ -478,7 +492,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) } break; case OB_GPENCIL_LEGACY: - OVERLAY_gpencil_cache_populate(data, ob); + OVERLAY_gpencil_legacy_cache_populate(data, ob); break; } } @@ -650,7 +664,7 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_armature_draw(data); OVERLAY_particle_draw(data); OVERLAY_metaball_draw(data); - OVERLAY_gpencil_draw(data); + OVERLAY_gpencil_legacy_draw(data); OVERLAY_extra_draw(data); if (pd->overlay.flag & V3D_OVERLAY_VIEWER_ATTRIBUTE) { OVERLAY_viewer_attribute_draw(data); @@ -718,11 +732,18 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_edit_particle_draw(data); break; case CTX_MODE_EDIT_GPENCIL: + if (U.experimental.use_grease_pencil_version3) { + OVERLAY_edit_grease_pencil_draw(data); + } + else { + OVERLAY_edit_gpencil_legacy_draw(data); + } + break; case CTX_MODE_PAINT_GPENCIL: case CTX_MODE_SCULPT_GPENCIL: case CTX_MODE_VERTEX_GPENCIL: case CTX_MODE_WEIGHT_GPENCIL: - OVERLAY_edit_gpencil_draw(data); + OVERLAY_edit_gpencil_legacy_draw(data); break; case CTX_MODE_SCULPT_CURVES: break; diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.cc b/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc similarity index 98% rename from source/blender/draw/engines/overlay/overlay_gpencil.cc rename to source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc index ab17d081e0b..de2bb5c0099 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.cc +++ b/source/blender/draw/engines/overlay/overlay_gpencil_legacy.cc @@ -23,7 +23,7 @@ #include "draw_common.h" #include "draw_manager_text.h" -void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata) +void OVERLAY_edit_gpencil_legacy_cache_init(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = vedata->stl->pd; @@ -205,7 +205,7 @@ void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata) } } -void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) +void OVERLAY_gpencil_legacy_cache_init(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = vedata->stl->pd; @@ -426,7 +426,7 @@ static void OVERLAY_gpencil_color_names(Object *ob) nullptr, ob, nullptr, overlay_gpencil_draw_stroke_color_name, ob, false, cfra); } -void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob) +void OVERLAY_gpencil_legacy_cache_populate(OVERLAY_Data *vedata, Object *ob) { const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; @@ -450,7 +450,7 @@ void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob) } } -void OVERLAY_gpencil_draw(OVERLAY_Data *vedata) +void OVERLAY_gpencil_legacy_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; @@ -459,7 +459,7 @@ void OVERLAY_gpencil_draw(OVERLAY_Data *vedata) } } -void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata) +void OVERLAY_edit_gpencil_legacy_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_grease_pencil.cc b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc new file mode 100644 index 00000000000..d4140c70e89 --- /dev/null +++ b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BKE_grease_pencil.hh" + +#include "overlay_private.hh" + +void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + GPUShader *sh; + DRWShadingGroup *grp; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA; + DRW_PASS_CREATE(psl->edit_grease_pencil_ps, (state | pd->clipping_state)); + + 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); +} + +void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + + DRWShadingGroup *points_grp = pd->edit_grease_pencil_points_grp; + if (points_grp) { + struct GPUBatch *geom = DRW_cache_grease_pencil_edit_points_get(ob, pd->cfra); + DRW_shgroup_call_no_cull(points_grp, geom, ob); + } +} + +void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + + if (psl->edit_grease_pencil_ps) { + DRW_draw_pass(psl->edit_grease_pencil_ps); + } +} \ No newline at end of file diff --git a/source/blender/draw/engines/overlay/overlay_private.hh b/source/blender/draw/engines/overlay/overlay_private.hh index e4ad06131c2..d0cf8238290 100644 --- a/source/blender/draw/engines/overlay/overlay_private.hh +++ b/source/blender/draw/engines/overlay/overlay_private.hh @@ -73,6 +73,7 @@ typedef struct OVERLAY_PassList { DRWPass *edit_gpencil_ps; DRWPass *edit_gpencil_gizmos_ps; DRWPass *edit_gpencil_curve_ps; + DRWPass *edit_grease_pencil_ps; DRWPass *edit_lattice_ps; DRWPass *edit_mesh_depth_ps[2]; DRWPass *edit_mesh_verts_ps[2]; @@ -250,6 +251,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *edit_lattice_wires_grp; DRWShadingGroup *edit_gpencil_points_grp; DRWShadingGroup *edit_gpencil_wires_grp; + DRWShadingGroup *edit_grease_pencil_points_grp; DRWShadingGroup *edit_gpencil_curve_handle_grp; DRWShadingGroup *edit_gpencil_curve_points_grp; DRWShadingGroup *edit_mesh_depth_grp[2]; @@ -555,11 +557,15 @@ void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_edit_surf_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_edit_curve_draw(OVERLAY_Data *vedata); -void OVERLAY_edit_gpencil_cache_init(OVERLAY_Data *vedata); -void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata); -void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob); -void OVERLAY_gpencil_draw(OVERLAY_Data *vedata); -void OVERLAY_edit_gpencil_draw(OVERLAY_Data *vedata); +void OVERLAY_edit_gpencil_legacy_cache_init(OVERLAY_Data *vedata); +void OVERLAY_gpencil_legacy_cache_init(OVERLAY_Data *vedata); +void OVERLAY_gpencil_legacy_cache_populate(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_gpencil_legacy_draw(OVERLAY_Data *vedata); +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_edit_grease_pencil_draw(OVERLAY_Data *vedata); void OVERLAY_edit_lattice_cache_init(OVERLAY_Data *vedata); void OVERLAY_edit_lattice_cache_populate(OVERLAY_Data *vedata, Object *ob); diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 704b8ea23ae..cc2e65a82cb 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -280,6 +280,7 @@ void DRW_cache_gpencil_sbuffer_clear(struct Object *ob); /* Grease Pencil */ struct GPUBatch *DRW_cache_grease_pencil_get(struct Object *ob, int cfra); +struct GPUBatch *DRW_cache_grease_pencil_edit_points_get(struct Object *ob, int cfra); struct GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(struct Object *ob, int cfra); struct GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(struct Object *ob, int cfra); diff --git a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc index aa6c7ff9a7c..1aa5a4fc2af 100644 --- a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc @@ -36,6 +36,12 @@ struct GreasePencilBatchCache { GPUIndexBuf *ibo; /** Batches */ GPUBatch *geom_batch; + GPUBatch *edit_points; + + /* Crazy-space point positions for original points. */ + GPUVertBuf *edit_points_pos; + /* Selection of original points. */ + GPUVertBuf *edit_points_selection; /** Cache is dirty. */ bool is_dirty; @@ -132,6 +138,10 @@ static void grease_pencil_batch_cache_clear(GreasePencil &grease_pencil) GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col); GPU_INDEXBUF_DISCARD_SAFE(cache->ibo); + GPU_BATCH_DISCARD_SAFE(cache->edit_points); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_pos); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_selection); + cache->is_dirty = true; } @@ -177,7 +187,7 @@ BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float har return packed; } -static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) +static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfra) { BLI_assert(grease_pencil.runtime != nullptr); GreasePencilBatchCache *cache = static_cast( @@ -199,6 +209,7 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) /* First, count how many vertices and triangles are needed for the whole object. Also record the * offsets into the curves for the vertices and triangles. */ int total_points_num = 0; + int total_verts_num = 0; int total_triangles_num = 0; int v_offset = 0; Vector> verts_start_offsets_per_visible_drawing; @@ -239,15 +250,17 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) v_offset += 1 + points.size() + (is_cyclic ? 1 : 0) + 1; } + total_points_num += curves.points_num(); + /* One vertex is stored before and after as padding. Cyclic strokes have one extra - * vertex. */ - total_points_num += curves.points_num() + num_cyclic + curves.curves_num() * 2; + * vertex.*/ + total_verts_num += curves.points_num() + num_cyclic + curves.curves_num() * 2; total_triangles_num += (curves.points_num() + num_cyclic) * 2; total_triangles_num += drawing.triangles().size(); if (drawing.has_stroke_buffer()) { const int num_buffer_points = drawing.stroke_buffer().size(); - total_points_num += 1 + num_buffer_points + 1; + total_verts_num += 1 + num_buffer_points + 1; total_triangles_num += num_buffer_points * 2; verts_start_offsets[curves.curves_range().size()] = v_offset; /* TODO: triangles for stroke buffer. */ @@ -258,6 +271,22 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) tris_start_offsets_per_visible_drawing.append(std::move(tris_start_offsets)); } + static GPUVertFormat format_edit_points_pos = {0}; + if (format_edit_points_pos.attr_len == 0) { + GPU_vertformat_attr_add(&format_edit_points_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + + static GPUVertFormat format_edit_points_selection = {0}; + if (format_edit_points_selection.attr_len == 0) { + GPU_vertformat_attr_add( + &format_edit_points_selection, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + + cache->edit_points_pos = GPU_vertbuf_create_with_format(&format_edit_points_pos); + cache->edit_points_selection = GPU_vertbuf_create_with_format(&format_edit_points_selection); + GPU_vertbuf_data_alloc(cache->edit_points_pos, total_points_num); + GPU_vertbuf_data_alloc(cache->edit_points_selection, total_points_num); + GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY; /* Create VBOs. */ GPUVertFormat *format = grease_pencil_stroke_format(); @@ -265,8 +294,8 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) cache->vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag); cache->vbo_col = GPU_vertbuf_create_with_format_ex(format_col, vbo_flag); /* Add extra space at the end of the buffer because of quad load. */ - GPU_vertbuf_data_alloc(cache->vbo, total_points_num + 2); - GPU_vertbuf_data_alloc(cache->vbo_col, total_points_num + 2); + GPU_vertbuf_data_alloc(cache->vbo, total_verts_num + 2); + GPU_vertbuf_data_alloc(cache->vbo_col, total_verts_num + 2); GPUIndexBufBuilder ibo; MutableSpan verts = { @@ -275,10 +304,17 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) MutableSpan cols = { static_cast(GPU_vertbuf_get_data(cache->vbo_col)), GPU_vertbuf_get_vertex_len(cache->vbo_col)}; + MutableSpan edit_points = { + static_cast(GPU_vertbuf_get_data(cache->edit_points_pos)), + GPU_vertbuf_get_vertex_len(cache->edit_points_pos)}; + MutableSpan edit_points_selection = { + static_cast(GPU_vertbuf_get_data(cache->edit_points_selection)), + GPU_vertbuf_get_vertex_len(cache->edit_points_selection)}; /* Create IBO. */ GPU_indexbuf_init(&ibo, GPU_PRIM_TRIS, total_triangles_num, 0xFFFFFFFFu); /* Fill buffers with data. */ + int drawing_start_offset = 0; for (const int drawing_i : drawings.index_range()) { const GreasePencilDrawing &drawing = *drawings[drawing_i]; const bke::CurvesGeometry &curves = drawing.geometry.wrap(); @@ -290,6 +326,8 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) "radius", ATTR_DOMAIN_POINT, 1.0f); const VArray opacities = *attributes.lookup_or_default( "opacity", ATTR_DOMAIN_POINT, 1.0f); + const VArray selection_float = *attributes.lookup_or_default( + ".selection", ATTR_DOMAIN_POINT, false); const VArray start_caps = *attributes.lookup_or_default( "start_cap", ATTR_DOMAIN_CURVE, 0); const VArray end_caps = *attributes.lookup_or_default( @@ -300,6 +338,12 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) const Span verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i]; const Span tris_start_offsets = tris_start_offsets_per_visible_drawing[drawing_i]; + edit_points.slice(drawing_start_offset, curves.points_num()).copy_from(curves.positions()); + MutableSpan selection_slice = edit_points_selection.slice(drawing_start_offset, + curves.points_num()); + selection_float.materialize(selection_slice); + drawing_start_offset += curves.points_num(); + auto populate_point = [&](IndexRange verts_range, int curve_i, int8_t start_cap, @@ -435,8 +479,8 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) } /* Mark last 2 verts as invalid. */ - verts[total_points_num + 0].mat = -1; - verts[total_points_num + 1].mat = -1; + verts[total_verts_num + 0].mat = -1; + verts[total_verts_num + 1].mat = -1; /* Also mark first vert as invalid. */ verts[0].mat = -1; @@ -448,6 +492,10 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra) GPU_vertbuf_use(cache->vbo); GPU_vertbuf_use(cache->vbo_col); + /* Create the batches */ + cache->edit_points = GPU_batch_create(GPU_PRIM_POINTS, cache->edit_points_pos, nullptr); + GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_selection, false); + cache->is_dirty = false; } @@ -498,17 +546,27 @@ GPUBatch *DRW_cache_grease_pencil_get(Object *ob, int cfra) using namespace blender::draw; GreasePencil &grease_pencil = *static_cast(ob->data); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra); - grease_pencil_batches_ensure(grease_pencil, cfra); + grease_pencil_geom_batch_ensure(grease_pencil, cfra); return cache->geom_batch; } +GPUBatch *DRW_cache_grease_pencil_edit_points_get(Object *ob, int cfra) +{ + using namespace blender::draw; + GreasePencil &grease_pencil = *static_cast(ob->data); + GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra); + grease_pencil_geom_batch_ensure(grease_pencil, cfra); + + return cache->edit_points; +} + GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(Object *ob, int cfra) { using namespace blender::draw; GreasePencil &grease_pencil = *static_cast(ob->data); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra); - grease_pencil_batches_ensure(grease_pencil, cfra); + grease_pencil_geom_batch_ensure(grease_pencil, cfra); return cache->vbo; } @@ -518,7 +576,7 @@ GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(Object *ob, int cfra) using namespace blender::draw; GreasePencil &grease_pencil = *static_cast(ob->data); GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra); - grease_pencil_batches_ensure(grease_pencil, cfra); + grease_pencil_geom_batch_ensure(grease_pencil, cfra); return cache->vbo_col; }