From 7c96f613e4d05f67f5cd9bf0cec29ca7ce51a3e4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 17 Aug 2017 01:38:07 +1000 Subject: DwM: Use Batch's for drawing selection Use mesh batch cache for mesh selection. Note that we could create the batches and free immediately so they don't take up memory. This resolves a problem where selection was limited to immediate-mode buffer size. --- source/blender/draw/intern/draw_cache_impl.h | 7 +- source/blender/draw/intern/draw_cache_impl_mesh.c | 464 +++++++++++++++++++-- source/blender/editors/space_view3d/drawobject.c | 61 ++- source/blender/gpu/GPU_shader.h | 1 + source/blender/gpu/intern/gpu_shader.c | 2 + .../gpu/shaders/gpu_shader_uniform_color_frag.glsl | 12 + 6 files changed, 503 insertions(+), 44 deletions(-) (limited to 'source') diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index f8feeb37b82..82972b9f75b 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -85,7 +85,8 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(struct Mesh *me, int defgroup); struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(struct Mesh *me); -struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide); struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me); @@ -95,6 +96,10 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me); +/* edit-mesh selection (use generic function for faces) */ +struct Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset); +struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset); void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 721db9f5f72..eddf2dc2fa4 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1427,13 +1427,32 @@ typedef struct MeshBatchCache { Gwn_VertBuf *pos_with_normals; Gwn_VertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */ + + /** + * Other uses are all positions or loose elements. + * This stores all visible elements, needed for selection. + */ + Gwn_VertBuf *ed_fcenter_pos_with_nor_and_sel; + Gwn_VertBuf *ed_edge_pos; + Gwn_VertBuf *ed_vert_pos; + Gwn_Batch *triangles_with_normals; /* Skip hidden (depending on paint select mode) */ Gwn_Batch *triangles_with_weights; Gwn_Batch *triangles_with_vert_colors; /* Always skip hidden */ + Gwn_Batch *triangles_with_select_mask; Gwn_Batch *triangles_with_select_id; + uint triangles_with_select_id_offset; + + Gwn_Batch *facedot_with_select_id; /* shares vbo with 'overlay_facedots' */ + Gwn_Batch *edges_with_select_id; + Gwn_Batch *verts_with_select_id; + + uint facedot_with_select_id_offset; + uint edges_with_select_id_offset; + uint verts_with_select_id_offset; Gwn_Batch *points_with_normals; Gwn_Batch *fancy_edges; /* owns its vertex buffer (not shared) */ @@ -1463,9 +1482,6 @@ typedef struct MeshBatchCache { Gwn_VertBuf *ed_lvert_nor; /* VertNor */ Gwn_VertBuf *ed_lvert_data; - Gwn_VertBuf *ed_fcenter_pos; - Gwn_VertBuf *ed_fcenter_nor; - Gwn_Batch *overlay_triangles; Gwn_Batch *overlay_triangles_nor; /* GWN_PRIM_POINTS */ Gwn_Batch *overlay_loose_edges; @@ -1583,11 +1599,18 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode) GWN_VERTBUF_DISCARD_SAFE(cache->ed_tri_data); GWN_VERTBUF_DISCARD_SAFE(cache->ed_ledge_data); GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data); - GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_nor); /* Contains select flag */ + GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */ + GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos); + GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles); GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_edges); GWN_BATCH_DISCARD_SAFE(cache->overlay_facedots); + /* Edit mode selection. */ + GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); break; case BKE_MESH_BATCH_DIRTY_NOCHECK: cache->is_really_dirty = true; @@ -1629,8 +1652,6 @@ static void mesh_batch_cache_clear(Mesh *me) GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos); GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor); GWN_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data); - GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos); - GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_nor); GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles); GWN_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor); GWN_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); @@ -1648,7 +1669,14 @@ static void mesh_batch_cache_clear(Mesh *me) GWN_BATCH_DISCARD_SAFE(cache->triangles_with_weights); GWN_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors); GWN_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos); + GWN_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos); + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_mask); GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->facedot_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); GWN_BATCH_DISCARD_SAFE(cache->fancy_edges); @@ -2054,6 +2082,286 @@ static Gwn_VertBuf *mesh_create_tri_pos_and_normals_visible_only( &vbo_dummy); } +static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + if (cache->ed_fcenter_pos_with_nor_and_sel == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + } + + const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); + int vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_fcenter_pos_with_nor_and_sel = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + for (int i = 0; i < vbo_len_capacity; ++i) { + float pcenter[3], pnor[3]; + bool selected = false; + + if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) { + + Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 }; + nor = GWN_normal_convert_i10_v3(pnor); + nor.w = selected ? 1 : 0; + GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor); + + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter); + + vidx += 1; + } + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + BLI_assert(vbo_len_capacity == vbo_len_used); + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->ed_fcenter_pos_with_nor_and_sel; +} + +static Gwn_VertBuf *mesh_batch_cache_get_edges_visible( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); + + if (cache->ed_edge_pos == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2; + int vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_edge_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *eed; + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co); + vidx += 1; + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co); + vidx += 1; + } + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->ed_edge_pos; +} + +static Gwn_VertBuf *mesh_batch_cache_get_verts_visible( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_vert_pos == NULL) { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, data; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata); + uint vidx = 0; + + Gwn_VertBuf *vbo = cache->ed_vert_pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *eve; + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co); + vidx += 1; + } + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const uint vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + UNUSED_VARS_NDEBUG(vbo_len_used); + } + + return cache->ed_vert_pos; +} + +static Gwn_VertBuf *mesh_create_facedot_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *efa; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_edges_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_edges_len_get(rdata) * 2; + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMEdge *eed; + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + +static Gwn_VertBuf *mesh_create_verts_select_id( + MeshRenderData *rdata, uint select_id_offset) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); + + Gwn_VertBuf *vbo; + { + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, col; } attr_id; + if (format.attrib_ct == 0) { + attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_I32, 1, GWN_FETCH_INT); + } + + const int vbo_len_capacity = mesh_render_data_verts_len_get(rdata); + int vidx = 0; + + vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + uint select_index = select_id_offset; + + if (rdata->edit_bmesh) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *eve; + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + int select_id; + GPU_select_index_get(select_index, &select_id); + GWN_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); + vidx += 1; + } + select_index += 1; + } + } + else { + /* not yet done! */ + BLI_assert(0); + } + const int vbo_len_used = vidx; + if (vbo_len_used != vbo_len_capacity) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + } + + return vbo; +} + static Gwn_VertBuf *mesh_create_tri_weights( MeshRenderData *rdata, bool use_hide, int defgroup) { @@ -2071,10 +2379,9 @@ static Gwn_VertBuf *mesh_create_tri_weights( attr_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); } - const int tri_len = mesh_render_data_looptri_len_get(rdata); - vbo = GWN_vertbuf_create_with_format(&format); + const int tri_len = mesh_render_data_looptri_len_get(rdata); const int vbo_len_capacity = tri_len * 3; int vbo_len_used = 0; GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); @@ -2176,7 +2483,7 @@ static Gwn_VertBuf *mesh_create_tri_vert_colors( } static Gwn_VertBuf *mesh_create_tri_select_id( - MeshRenderData *rdata, bool use_hide) + MeshRenderData *rdata, bool use_hide, uint select_id_offset) { BLI_assert( rdata->types & @@ -2207,7 +2514,7 @@ static Gwn_VertBuf *mesh_create_tri_select_id( if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { const int poly_index = BM_elem_index_get(ltri[0]->f); int select_id; - GPU_select_index_get(poly_index + 1, &select_id); + GPU_select_index_get(poly_index + select_id_offset, &select_id); for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); } @@ -2220,7 +2527,7 @@ static Gwn_VertBuf *mesh_create_tri_select_id( const int poly_index = mlt->poly; if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) { int select_id; - GPU_select_index_get(poly_index + 1, &select_id); + GPU_select_index_get(poly_index + select_id_offset, &select_id); for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { GWN_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); } @@ -3006,17 +3313,23 @@ Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_vert_colors(Mesh } -struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide) +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id( + struct Mesh *me, bool use_hide, uint select_id_offset) { MeshBatchCache *cache = mesh_batch_cache_get(me); + if (cache->triangles_with_select_id_offset != select_id_offset) { + cache->triangles_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); + } + if (cache->triangles_with_select_id == NULL) { const int datatype = MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; MeshRenderData *rdata = mesh_render_data_create(me, datatype); cache->triangles_with_select_id = GWN_batch_create_ex( - GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide), NULL, GWN_BATCH_OWNS_VBO); + GWN_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GWN_BATCH_OWNS_VBO); Gwn_VertBuf *vbo_tris = use_hide ? mesh_create_tri_pos_and_normals_visible_only(rdata) : @@ -3029,6 +3342,31 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh return cache->triangles_with_select_id; } +/** + * Same as #DRW_mesh_batch_cache_get_triangles_with_select_id + * without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces. + */ +struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + if (cache->triangles_with_select_mask == NULL) { + const int datatype = + MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; + MeshRenderData *rdata = mesh_render_data_create(me, datatype); + + Gwn_VertBuf *vbo_tris = use_hide ? + mesh_create_tri_pos_and_normals_visible_only(rdata) : + mesh_batch_cache_get_tri_pos_and_normals(rdata, cache); + + cache->triangles_with_select_mask = GWN_batch_create_ex( + GWN_PRIM_TRIS, vbo_tris, NULL, use_hide ? GWN_BATCH_OWNS_VBO : 0); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_select_mask; +} + Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -3238,46 +3576,90 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me) if (cache->overlay_facedots == NULL) { MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); - static Gwn_VertFormat format = { 0 }; - static struct { uint pos, data; } attr_id; - if (format.attrib_ct == 0) { - attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - attr_id.data = GWN_vertformat_attr_add(&format, "norAndFlag", GWN_COMP_I10, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); - } + cache->overlay_facedots = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL); - const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); - int vidx = 0; + mesh_render_data_free(rdata); + } - Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); - GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); - for (int i = 0; i < vbo_len_capacity; ++i) { - float pcenter[3], pnor[3]; - bool selected = false; + return cache->overlay_facedots; +} - if (mesh_render_data_pnors_pcenter_select_get(rdata, i, pnor, pcenter, &selected)) { +Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); - Gwn_PackedNormal nor = { .x = 0, .y = 0, .z = -511 }; - nor = GWN_normal_convert_i10_v3(pnor); - nor.w = selected ? 1 : 0; - GWN_vertbuf_attr_set(vbo, attr_id.data, vidx, &nor); + if (cache->facedot_with_select_id_offset != select_id_offset) { + cache->facedot_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + } - GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx, pcenter); + if (cache->facedot_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); - vidx += 1; + /* We only want the 'pos', not the normals or flag. + * Use since this is almost certainly already created. */ + cache->facedot_with_select_id = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL); - } - } - const int vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GWN_vertbuf_data_resize(vbo, vbo_len_used); - } + GWN_batch_vertbuf_add_ex( + cache->facedot_with_select_id, + mesh_create_facedot_select_id(rdata, select_id_offset), true); + + mesh_render_data_free(rdata); + } + + return cache->facedot_with_select_id; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->edges_with_select_id_offset != select_id_offset) { + cache->edges_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->edges_with_select_id); + } - cache->overlay_facedots = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO); + if (cache->edges_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); + + cache->edges_with_select_id = GWN_batch_create( + GWN_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->edges_with_select_id, + mesh_create_edges_select_id(rdata, select_id_offset), true); mesh_render_data_free(rdata); } - return cache->overlay_facedots; + return cache->edges_with_select_id; +} + +Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->verts_with_select_id_offset != select_id_offset) { + cache->verts_with_select_id_offset = select_id_offset; + GWN_BATCH_DISCARD_SAFE(cache->verts_with_select_id); + } + + if (cache->verts_with_select_id == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); + + cache->verts_with_select_id = GWN_batch_create( + GWN_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL); + + GWN_batch_vertbuf_add_ex( + cache->verts_with_select_id, + mesh_create_verts_select_id(rdata, select_id_offset), true); + + mesh_render_data_free(rdata); + } + + return cache->verts_with_select_id; } Gwn_Batch **DRW_mesh_batch_cache_get_surface_shaded( diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 2acc7241f86..5698b2fe08a 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -118,6 +118,8 @@ /* prototypes */ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos); +// #define USE_MESH_DM_SELECT + /* Workaround for sequencer scene render mode. * * Strips doesn't use DAG to update objects or so, which @@ -9369,6 +9371,7 @@ void draw_object_select( /* ***************** BACKBUF SEL (BBS) ********* */ + static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -9410,6 +9413,7 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset) immUnbindProgram(); } +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { @@ -9442,7 +9446,17 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) immUnbindProgram(); } +#else +static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) { drawBMOffset_userData *data = userData; @@ -9482,7 +9496,19 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) immUnbindProgram(); } +#else +static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset) +{ + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select) { UNUSED_VARS(dm); @@ -9535,7 +9561,29 @@ static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select immUnbindProgram(); } +#else +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *UNUSED(dm), const bool use_select) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch; + if (use_select) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); + } + else { + int selcol; + GPU_select_index_get(0, &selcol); + batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); + GWN_batch_uniform_1i(batch, "color", selcol); + GWN_batch_draw(batch); + } +} +#endif + +#ifdef USE_MESH_DM_SELECT static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3])) { drawBMOffset_userData *data = (drawBMOffset_userData *)userData; @@ -9567,6 +9615,15 @@ static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm) immUnbindProgram(); } +#else +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *UNUSED(dm)) +{ + Mesh *me = em->ob->data; + Gwn_Batch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1); + GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GWN_batch_draw(batch); +} +#endif /* two options, facecolors or black */ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, @@ -9641,10 +9698,10 @@ static void bbs_mesh_solid_faces(Scene *scene, Object *ob) UNUSED_VARS(scene, bbs_mesh_solid_hide__setDrawOpts, bbs_mesh_solid__setDrawOpts); Gwn_Batch *batch; if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) { - batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true); + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); } else { - batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false); + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1); } GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); GWN_batch_draw(batch); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 7c8ee07eb88..5b62bafd402 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -118,6 +118,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_2D_DIAG_STRIPES, /* for simple 3D drawing */ GPU_SHADER_3D_UNIFORM_COLOR, + GPU_SHADER_3D_UNIFORM_COLOR_U32, GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, GPU_SHADER_3D_FLAT_COLOR, GPU_SHADER_3D_FLAT_COLOR_U32, /* use for select-id's */ diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index e67e5bc933d..5d5be2ec4ef 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -663,6 +663,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_shuffle_color_frag_glsl }, [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_3D_UNIFORM_COLOR_U32] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, [GPU_SHADER_3D_FLAT_COLOR_U32] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, @@ -767,6 +768,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) defines = "#define USE_INSTANCE_COLOR;\n"; break; case GPU_SHADER_3D_FLAT_COLOR_U32: + case GPU_SHADER_3D_UNIFORM_COLOR_U32: defines = "#define USE_COLOR_U32;\n"; break; case GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR: diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl index 5dd1352adc5..118a661863d 100644 --- a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl @@ -1,9 +1,21 @@ +#if defined(USE_COLOR_U32) +uniform uint color; +#else uniform vec4 color; +#endif out vec4 fragColor; void main() { +#if defined(USE_COLOR_U32) + fragColor = vec4( + ((color ) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 24) ) * (1.0f / 255.0f)); +#else fragColor = color; +#endif } -- cgit v1.2.3