[Bf-blender-cvs] [e49d9555418] master: Wireframe: Refactor to use GL_LINES instead of triangles with alpha blend
Clément Foucault
noreply at git.blender.org
Mon Feb 18 14:18:14 CET 2019
Commit: e49d9555418d571f0585bf9a33aed90008e72e2c
Author: Clément Foucault
Date: Tue Feb 12 23:22:36 2019 +0100
Branches: master
https://developer.blender.org/rBe49d9555418d571f0585bf9a33aed90008e72e2c
Wireframe: Refactor to use GL_LINES instead of triangles with alpha blend
This gets rid of the progressive fading of the edges as it does not work
with depth perception (sorting problem with alpha blending).
===================================================================
M source/blender/draw/intern/draw_cache_impl_mesh.c
M source/blender/draw/modes/overlay_mode.c
M source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
M source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
===================================================================
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 0228f108c1d..6fe0344bf76 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -1176,7 +1176,7 @@ static int mesh_render_data_loose_verts_len_get_maybe_mapped(const MeshRenderDat
return ((rdata->mapped.use == false) ? rdata->loose_vert_len : rdata->mapped.loose_vert_len);
}
-static int UNUSED_FUNCTION(mesh_render_data_edges_len_get)(const MeshRenderData *rdata)
+static int mesh_render_data_edges_len_get(const MeshRenderData *rdata)
{
BLI_assert(rdata->types & MR_DATATYPE_EDGE);
return rdata->edge_len;
@@ -1750,6 +1750,7 @@ typedef struct MeshBatchCache {
GPUVertBuf *loop_pos_nor;
GPUVertBuf *loop_uv_tan;
GPUVertBuf *loop_vcol;
+ GPUVertBuf *loop_edge_fac;
} ordered;
/* Tesselated: (all verts specified for each triangles).
@@ -1795,13 +1796,14 @@ typedef struct MeshBatchCache {
/* Indices to vloops. */
GPUIndexBuf *loops_tris;
GPUIndexBuf *loops_lines;
+ GPUIndexBuf *loops_line_strips;
/* Edit mode. */
GPUIndexBuf *edit_loops_points; /* verts */
GPUIndexBuf *edit_loops_lines; /* edges */
GPUIndexBuf *edit_loops_tris; /* faces */
/* Edit UVs */
GPUIndexBuf *edituv_loops_points; /* verts */
- GPUIndexBuf *edituv_loops_lines; /* edges */
+ GPUIndexBuf *edituv_loops_line_strips; /* edges */
GPUIndexBuf *edituv_loops_tri_fans; /* faces */
} ibo;
@@ -1832,6 +1834,7 @@ typedef struct MeshBatchCache {
GPUBatch *all_edges;
GPUBatch *loose_edges;
GPUBatch *edge_detection;
+ GPUBatch *wire_edges; /* Individual edges with face normals. */
GPUBatch *wire_loops; /* Loops around faces. */
GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
GPUBatch *wire_triangles; /* Triangles for object mode wireframe. */
@@ -1998,7 +2001,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv_data);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_area);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_angle);
@@ -2847,6 +2850,115 @@ static void mesh_create_weights(MeshRenderData *rdata, GPUVertBuf *vbo, DRW_Mesh
GPU_vertbuf_attr_fill(vbo, attr_id.weight, vert_weight);
}
+static float mesh_loop_edge_factor_get(
+ const float f_no[3], const float v_co[3], const float v_no[3], const float v_next_co[3])
+{
+ float enor[3], evec[3];
+ sub_v3_v3v3(evec, v_next_co, v_co);
+ cross_v3_v3v3(enor, v_no, evec);
+ normalize_v3(enor);
+ float d = fabsf(dot_v3v3(enor, f_no));
+ /* Rescale to the slider range. */
+ d *= (1.0f / 0.065f);
+ CLAMP(d, 0.0f, 1.0f);
+ return d;
+}
+
+static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo)
+{
+ static GPUVertFormat format = { 0 };
+ static struct { uint wd; } attr_id;
+ if (format.attr_len == 0) {
+ attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, loop_len);
+
+ GPUVertBufRaw wd_step;
+ GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
+
+ if (rdata->mapped.use == false) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter_efa, iter_loop;
+ BMFace *efa;
+ BMLoop *loop;
+ uint f;
+
+ BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, f) {
+ BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
+ float ratio = mesh_loop_edge_factor_get(efa->no, loop->v->co, loop->v->no, loop->next->v->co);
+ *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 255;
+ }
+ }
+ BLI_assert(GPU_vertbuf_raw_used(&wd_step) == loop_len);
+ }
+ else {
+ const MVert *mvert = rdata->mvert;
+ const MPoly *mpoly = rdata->mpoly;
+ const MLoop *mloop = rdata->mloop;
+ MEdge *medge = (MEdge *)rdata->medge;
+ bool use_edge_render = false;
+
+ /* TODO(fclem) We don't need them to be packed. But we need rdata->poly_normals */
+ mesh_render_data_ensure_poly_normals_pack(rdata);
+
+ /* Reset flag */
+ for (int edge = 0; edge < edge_len; ++edge) {
+ /* NOTE: not thread safe. */
+ medge[edge].flag &= ~ME_EDGE_TMP_TAG;
+
+ /* HACK(fclem) Feels like a hack. Detecting the need for edge render. */
+ if ((medge[edge].flag & ME_EDGERENDER) == 0) {
+ use_edge_render = true;
+ }
+ }
+
+ for (int a = 0; a < poly_len; a++, mpoly++) {
+ const float *fnor = rdata->poly_normals[a];
+ for (int b = 0; b < mpoly->totloop; b++) {
+ const MLoop *ml1 = &mloop[mpoly->loopstart + b];
+ const MLoop *ml2 = &mloop[mpoly->loopstart + (b + 1) % mpoly->totloop];
+
+ /* Will only work for edges that have an odd number of faces connected. */
+ MEdge *ed = (MEdge *)rdata->medge + ml1->e;
+ ed->flag ^= ME_EDGE_TMP_TAG;
+
+ if (use_edge_render) {
+ *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = (ed->flag & ME_EDGERENDER) ? 255 : 0;
+ }
+ else {
+ float vnor_f[3];
+ normal_short_to_float_v3(vnor_f, mvert[ml1->v].no);
+ float ratio = mesh_loop_edge_factor_get(fnor,
+ mvert[ml1->v].co,
+ vnor_f,
+ mvert[ml2->v].co);
+ *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 253 + 1;
+ }
+ }
+ }
+ /* Gather non-manifold edges. */
+ for (int l = 0; l < loop_len; l++, mloop++) {
+ MEdge *ed = (MEdge *)rdata->medge + mloop->e;
+ if (ed->flag & ME_EDGE_TMP_TAG) {
+ uchar data = 255;
+ GPU_vertbuf_attr_set(vbo, attr_id.wd, l, &data);
+ }
+ }
+
+ BLI_assert(loop_len == GPU_vertbuf_raw_used(&wd_step));
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
{
/* TODO deduplicate format creation*/
@@ -3603,6 +3715,72 @@ static void mesh_create_surf_tris(MeshRenderData *rdata, GPUIndexBuf *ibo, const
static void mesh_create_loops_lines(
MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
+{
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, loop_len);
+
+ if (rdata->mapped.use == false) {
+ if (rdata->edit_bmesh) {
+ BMesh *bm = rdata->edit_bmesh->bm;
+ BMIter iter;
+ BMEdge *bm_edge;
+
+ BM_ITER_MESH (bm_edge, &iter, bm, BM_EDGES_OF_MESH) {
+ /* use_hide always for edit-mode */
+ if (!BM_elem_flag_test(bm_edge, BM_ELEM_HIDDEN) &&
+ bm_edge->l != NULL)
+ {
+ BMLoop *bm_loop1 = BM_vert_find_first_loop(bm_edge->v1);
+ BMLoop *bm_loop2 = BM_vert_find_first_loop(bm_edge->v2);
+ int v1 = BM_elem_index_get(bm_loop1);
+ int v2 = BM_elem_index_get(bm_loop2);
+ if (v1 > v2) {
+ SWAP(int, v1, v2);
+ }
+ GPU_indexbuf_add_line_verts(&elb, v1, v2);
+ }
+ }
+ }
+ else {
+ MLoop *mloop = (MLoop *)rdata->mloop;
+ MEdge *medge = (MEdge *)rdata->medge;
+
+ /* Reset flag */
+ for (int edge = 0; edge < edge_len; ++edge) {
+ /* NOTE: not thread safe. */
+ medge[edge].flag &= ~ME_EDGE_TMP_TAG;
+ }
+
+ for (int poly = 0; poly < poly_len; poly++) {
+ const MPoly *mp = &rdata->mpoly[poly];
+ if (!(use_hide && (mp->flag & ME_HIDE))) {
+ for (int j = 0; j < mp->totloop; j++) {
+ MEdge *ed = (MEdge *)rdata->medge + mloop[mp->loopstart + j].e;
+ if ((ed->flag & ME_EDGE_TMP_TAG) == 0) {
+ ed->flag |= ME_EDGE_TMP_TAG;
+ int v1 = mp->loopstart + j;
+ int v2 = mp->loopstart + (j + 1) % mp->totloop;
+ GPU_indexbuf_add_line_verts(&elb, v1, v2);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* Implement ... eventually if needed. */
+ BLI_assert(0);
+ }
+
+ GPU_indexbuf_build_in_place(&elb, ibo);
+}
+
+static void mesh_create_loops_line_strips(
+ MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
{
const int loop_len = mesh_render_data_loops_len_get(rdata);
const int poly_len = mesh_render_data_polys_len_get(rdata);
@@ -4125,7 +4303,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- return DRW_batch_request(&cache->batch.wire_triangles);
+ return DRW_batch_request(&cache->batch.wire_edges);
}
GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
@@ -4705,7 +4883,7 @@ void DRW_mesh_batch_cache_create_requested(
GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv);
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_lines);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
/* We only clear the batches as they may already have been referenced. */
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area);
@@ -4750,11 +4928,16 @@ void DRW_mesh_batch_cache_create_requested(
DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights);
}
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) {
- DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_lines);
+ DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips);
DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor);
}
+ if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES))
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list