[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