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.
This commit is contained in:
2017-08-17 01:38:07 +10:00
parent a4068d0083
commit 7c96f613e4
6 changed files with 510 additions and 51 deletions

View File

@@ -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);

View File

@@ -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,41 +3576,8 @@ 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);
}
const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata);
int vidx = 0;
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;
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);
}
cache->overlay_facedots = GWN_batch_create_ex(GWN_PRIM_POINTS, vbo, NULL, GWN_BATCH_OWNS_VBO);
cache->overlay_facedots = GWN_batch_create(
GWN_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL);
mesh_render_data_free(rdata);
}
@@ -3280,6 +3585,83 @@ Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
return cache->overlay_facedots;
}
Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
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);
}
if (cache->facedot_with_select_id == NULL) {
MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
/* 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);
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);
}
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->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(
Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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:

View File

@@ -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
}