Wireframe: Optimization: Only draw triangles that have edges

This only happens after a certain threshold.

We sort triangles into 2 bins (start and end of the buffer) based on a
threshold and just draw the start bin if the wireframe slider is low enough.

This optimization is disabled for deformed meshes.

This should help resolve (to some extent) T58188.
This commit is contained in:
Clément Foucault 2018-12-04 01:30:07 +01:00
parent 89ef69d23c
commit f1975a4639
Notes: blender-bot 2023-02-14 08:42:54 +01:00
Referenced by commit e929cad706, DRW: Rework wireframe overlay implementation
7 changed files with 108 additions and 56 deletions

View File

@ -694,23 +694,23 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
/* Returns a buffer texture. */
void DRW_cache_object_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
switch (ob->type) {
case OB_MESH:
DRW_cache_mesh_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_cache_mesh_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
break;
case OB_CURVE:
DRW_cache_curve_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_cache_curve_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
break;
case OB_SURF:
DRW_cache_surf_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_cache_surf_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
break;
case OB_FONT:
DRW_cache_text_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_cache_text_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
break;
case OB_MBALL:
DRW_cache_mball_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_cache_mball_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
break;
}
}
@ -3063,12 +3063,12 @@ GPUBatch *DRW_cache_mesh_surface_get(Object *ob, bool use_hide)
}
void DRW_cache_mesh_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
DRW_mesh_batch_cache_get_wireframes_face_texbuf(me, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_mesh_batch_cache_get_wireframes_face_texbuf(me, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
}
GPUBatch *DRW_cache_mesh_loose_edges_get(Object *ob)
@ -3263,12 +3263,12 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob)
}
void DRW_cache_curve_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
}
/* Return list of batches */
@ -3295,10 +3295,10 @@ GPUBatch *DRW_cache_mball_surface_get(Object *ob)
}
void DRW_cache_mball_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
BLI_assert(ob->type == OB_MBALL);
DRW_metaball_batch_cache_get_wireframes_face_texbuf(ob, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_metaball_batch_cache_get_wireframes_face_texbuf(ob, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
}
GPUBatch **DRW_cache_mball_surface_shaded_get(
@ -3336,7 +3336,7 @@ GPUBatch *DRW_cache_text_surface_get(Object *ob)
void DRW_cache_text_face_wireframe_get(
Object *ob,
struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
@ -3346,7 +3346,7 @@ void DRW_cache_text_face_wireframe_get(
*r_tri_count = 0;
return;
}
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
}
GPUBatch **DRW_cache_text_surface_shaded_get(
@ -3390,12 +3390,12 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob)
}
void DRW_cache_surf_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count);
DRW_curve_batch_cache_get_wireframes_face_texbuf(cu, ob->runtime.curve_cache, r_vert_tx, r_faceid_tx, r_tri_count, reduce_len);
}
/* Return list of batches */

View File

@ -59,7 +59,7 @@ struct GPUBatch **DRW_cache_object_surface_material_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, bool use_hide,
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
void DRW_cache_object_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
/* Empties */
struct GPUBatch *DRW_cache_plain_axes_get(void);
@ -154,7 +154,7 @@ struct GPUBatch **DRW_cache_mesh_surface_shaded_get(
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob, bool use_hide);
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
void DRW_cache_mesh_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
@ -165,7 +165,7 @@ struct GPUBatch **DRW_cache_curve_surface_shaded_get(
struct GPUBatch *DRW_cache_curve_surface_verts_get(struct Object *ob);
struct GPUBatch *DRW_cache_curve_edge_wire_get(struct Object *ob);
void DRW_cache_curve_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
/* edit-mode */
struct GPUBatch *DRW_cache_curve_edge_normal_get(struct Object *ob, float normal_size);
struct GPUBatch *DRW_cache_curve_edge_overlay_get(struct Object *ob);
@ -177,7 +177,7 @@ struct GPUBatch *DRW_cache_text_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_text_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
void DRW_cache_text_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
/* edit-mode */
struct GPUBatch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
struct GPUBatch *DRW_cache_text_select_overlay_get(struct Object *ob);
@ -187,7 +187,7 @@ struct GPUBatch *DRW_cache_surf_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_surf_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
void DRW_cache_surf_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
/* Lattice */
struct GPUBatch *DRW_cache_lattice_verts_get(struct Object *ob);
@ -211,6 +211,6 @@ struct GPUBatch *DRW_cache_particles_get_prim(int type);
struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
void DRW_cache_mball_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count, bool reduce_len);
#endif /* __DRAW_CACHE_H__ */

View File

@ -77,13 +77,13 @@ struct GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
struct GPUMaterial **gpumat_array, uint gpumat_array_len);
void DRW_curve_batch_cache_get_wireframes_face_texbuf(
struct Curve *cu, struct CurveCache *ob_curve_cache,
struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count, bool reduce_len);
/* Metaball */
struct GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
struct Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
struct Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count, bool reduce_len);
/* Curve (Font) */
struct GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
@ -162,7 +162,7 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me,
struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset);
/* Object mode Wireframe overlays */
void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count, bool reduce_len);
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);

View File

@ -1076,7 +1076,7 @@ GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
void DRW_curve_batch_cache_get_wireframes_face_texbuf(
Curve *cu, CurveCache *ob_curve_cache,
GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count, bool UNUSED(reduce_len))
{
CurveBatchCache *cache = curve_batch_cache_get(cu);

View File

@ -2065,6 +2065,7 @@ typedef struct MeshBatchCache {
GPUVertBuf *edges_face_overlay;
GPUTexture *edges_face_overlay_tx;
int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay(_adj)_tx */
int edges_face_overlay_tri_count_low; /* Number of tri that are sure to produce edges. */
/* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
* to minimize data transfer for skinned mesh. */
@ -4303,24 +4304,33 @@ static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
return eh;
}
static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderData *rdata)
static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(
MeshRenderData *rdata, MeshBatchCache *cache, bool reduce_len)
{
if (cache->edges_face_overlay != NULL) {
return cache->edges_face_overlay;
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
GPUVertFormat format = {0};
uint index_id = GPU_vertformat_attr_add(&format, "index", GPU_COMP_U32, 1, GPU_FETCH_INT);
GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
GPUVertBuf *vbo = cache->edges_face_overlay = GPU_vertbuf_create_with_format(&format);
int vbo_len_capacity = tri_len * 3;
GPU_vertbuf_data_alloc(vbo, vbo_len_capacity);
int vidx = 0;
int vidx_end = vbo_len_capacity;
EdgeHash *eh = NULL;
eh = create_looptri_edge_adjacency_hash(rdata);
for (int i = 0; i < tri_len; i++) {
uint vdata[3] = {0, 0, 0};
bool edge_is_real[3];
bool face_has_edges = false;
const MVert *mvert = rdata->mvert;
const MEdge *medge = rdata->medge;
const MLoop *mloop = rdata->mloop;
const MLoopTri *mlt = rdata->mlooptri + i;
@ -4329,41 +4339,80 @@ static GPUVertBuf *mesh_batch_cache_create_edges_overlay_texture_buf(MeshRenderD
for (j = 2, j_next = 0; j_next < 3; j = j_next++) {
const MEdge *ed = &medge[mloop[mlt->tri[j]].e];
const uint tri_edge[2] = {mloop[mlt->tri[j]].v, mloop[mlt->tri[j_next]].v};
const bool is_edge_real = (
edge_is_real[j] = (
((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) ||
((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0])));
edge_is_real[j] = is_edge_real;
}
if (edge_is_real[0] || edge_is_real[1] || edge_is_real[2]) {
/* Decide if face has at least a "dominant" edge. */
/* Try to do the same facing approximation as in the shader. */
float fnor[3];
if (reduce_len) {
normal_tri_v3(fnor,
mvert[mloop[mlt->tri[0]].v].co,
mvert[mloop[mlt->tri[1]].v].co,
mvert[mloop[mlt->tri[2]].v].co);
}
for (int e = 0; e < 3; e++) {
int v0 = mloop[mlt->tri[e]].v;
int v1 = mloop[mlt->tri[(e + 1) % 3]].v;
vdata[e] = (uint)v0;
EdgeAdjacentVerts *eav = BLI_edgehash_lookup(eh, v0, v1);
/* Real edge */
if (edge_is_real[e]) {
vdata[e] |= (1 << 30);
}
/* If Non Manifold. */
if (eav->vert_index[1] == -1) {
face_has_edges = true;
vdata[e] |= (1u << 31);
}
/* Search for dominant edge. */
if (reduce_len && !face_has_edges && edge_is_real[e]) {
int v2 = mloop[mlt->tri[(e + 2) % 3]].v;
/* Select the right opposite vertex */
v2 = (eav->vert_index[1] == v2) ? eav->vert_index[0] : eav->vert_index[1];
float fnor_adj[3];
normal_tri_v3(fnor_adj,
mvert[v1].co,
mvert[v0].co,
mvert[v2].co);
float fac = dot_v3v3(fnor_adj, fnor);
if (fac < 0.999f) {
face_has_edges = true;
}
}
}
}
if (!face_has_edges) {
vidx_end -= 3;
}
for (int e = 0; e < 3; e++) {
int v0 = mloop[mlt->tri[e]].v;
int v1 = mloop[mlt->tri[(e + 1) % 3]].v;
EdgeAdjacentVerts *eav = BLI_edgehash_lookup(eh, v0, v1);
uint value = (uint)v0;
/* Real edge */
if (edge_is_real[e]) {
value |= (1 << 30);
/* Add faces most likely to draw anything at the begining of the VBO
* to enable fast drawing the visible edges. */
if (face_has_edges) {
GPU_vertbuf_attr_set(vbo, index_id, vidx++, &vdata[e]);
}
/* Non-manifold edge */
if (eav->vert_index[1] == -1) {
value |= (1u << 31);
else {
GPU_vertbuf_attr_set(vbo, index_id, vidx_end+e, &vdata[e]);
}
GPU_vertbuf_attr_set(vbo, index_id, vidx++, &value);
}
}
cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 3;
cache->edges_face_overlay_tri_count_low = vidx / 3;
BLI_edgehash_free(eh, MEM_freeN);
int vbo_len_used = vidx;
if (vbo_len_capacity != vbo_len_used) {
GPU_vertbuf_data_resize(vbo, vbo_len_used);
}
return vbo;
}
static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(
MeshRenderData *rdata, MeshBatchCache *cache, bool reduce_len)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
@ -4373,12 +4422,11 @@ static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData
return cache->edges_face_overlay_tx;
}
GPUVertBuf *vbo = cache->edges_face_overlay = mesh_batch_cache_create_edges_overlay_texture_buf(rdata);
GPUVertBuf *vbo = mesh_batch_cache_create_edges_overlay_texture_buf(rdata, cache, reduce_len);
/* Upload data early because we need to create the texture for it. */
GPU_vertbuf_use(vbo);
cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo);
cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 3;
return cache->edges_face_overlay_tx;
}
@ -5052,7 +5100,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
}
void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count, bool reduce_len)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@ -5061,13 +5109,13 @@ void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
MeshRenderData *rdata = mesh_render_data_create(me, options);
mesh_batch_cache_get_edges_overlay_texture_buf(rdata, cache);
mesh_batch_cache_get_edges_overlay_texture_buf(rdata, cache, reduce_len);
mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(rdata, cache);
mesh_render_data_free(rdata);
}
*tri_count = cache->edges_face_overlay_tri_count;
*tri_count = reduce_len ? cache->edges_face_overlay_tri_count_low : cache->edges_face_overlay_tri_count;
*face_indices = cache->edges_face_overlay_tx;
*verts_data = cache->pos_in_order_tx;
}

View File

@ -233,7 +233,7 @@ GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb,
}
void DRW_metaball_batch_cache_get_wireframes_face_texbuf(
Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count)
Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count, bool UNUSED(reduce_len))
{
if (!BKE_mball_is_basis(ob)) {
*verts_data = NULL;

View File

@ -288,9 +288,13 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
}
else {
/* Manually tweaked so the shader hidding matches. */
const bool reduced_tri_len = (stl->g_data->wire_step_param[1] < 0.9988) &&
!(DRW_state_is_select() || DRW_state_is_depth()) &&
!BKE_object_is_deform_modified(draw_ctx->scene, ob);
int tri_count;
GPUTexture *verts = NULL, *faceids;
DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count);
DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count, reduced_tri_len);
if (verts) {
float *rim_col = ts.colorWire;
if ((ob->base_flag & BASE_SELECTED) != 0) {