[Bf-blender-cvs] [712885c30ef] blender2.8: DRW: Add wireframe buffer texture generation for wireframe drawing.

Clément Foucault noreply at git.blender.org
Thu May 31 19:12:17 CEST 2018


Commit: 712885c30ef2a8dbde91b7d8b4ffb9784a70fca5
Author: Clément Foucault
Date:   Thu May 31 18:43:19 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB712885c30ef2a8dbde91b7d8b4ffb9784a70fca5

DRW: Add wireframe buffer texture generation for wireframe drawing.

Only OB_MESH is supported for now.

Creates a simple index buffer with negative indices if the edges is not a
real edge.

Also create the buffer texture representation of this buffer along with the
pos_in_order buffer texture.

===================================================================

M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/draw/intern/draw_cache_impl_mesh.c

===================================================================

diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index ddf41ceff8a..33fb801af5a 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -502,7 +502,6 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob)
 	}
 }
 
-/* Returns a buffer texture. */
 Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
 {
 	switch (ob->type) {
@@ -515,6 +514,19 @@ Gwn_Batch *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)
+{
+	switch (ob->type) {
+		case OB_MESH:
+			DRW_mesh_batch_cache_get_wireframes_face_texbuf((Mesh *)ob->data, r_vert_tx, r_faceid_tx, r_tri_count);
+
+		/* TODO, should match 'DRW_cache_object_surface_get' */
+	}
+}
+
+
 Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
 {
 	switch (ob->type) {
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 1fd6b22c221..e962d513c9b 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -53,6 +53,8 @@ struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob);
 struct Gwn_Batch **DRW_cache_object_surface_material_get(
         struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
         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);
 
 /* Empties */
 struct Gwn_Batch *DRW_cache_plain_axes_get(void);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index f77dafc9b31..8a8d41cb38a 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -28,6 +28,7 @@
 
 struct CurveCache;
 struct GPUMaterial;
+struct GPUTexture;
 struct Gwn_Batch;
 struct Gwn_IndexBuf;
 struct Gwn_VertBuf;
@@ -121,6 +122,9 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
 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);
+/* 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);
 
 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 e1b66a85ca2..d6651125b58 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -1541,11 +1541,12 @@ static void add_overlay_loose_vert(
 
 typedef struct MeshBatchCache {
 	Gwn_VertBuf *pos_in_order;
-	Gwn_VertBuf *nor_in_order;
 	Gwn_IndexBuf *edges_in_order;
 	Gwn_IndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */
 	Gwn_IndexBuf *triangles_in_order;
 
+	GPUTexture *pos_in_order_tx; /* Depending on pos_in_order */
+
 	Gwn_Batch *all_verts;
 	Gwn_Batch *all_edges;
 	Gwn_Batch *all_triangles;
@@ -1584,6 +1585,9 @@ typedef struct MeshBatchCache {
 
 	Gwn_Batch *edge_detection;
 
+	GPUTexture *edges_face_overlay_tx;
+	int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay_tx */
+
 	/* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
 	 * to minimise data transfer for skinned mesh. */
 	Gwn_VertFormat shaded_triangles_format;
@@ -1816,6 +1820,7 @@ static void mesh_batch_cache_clear(Mesh *me)
 	GWN_BATCH_DISCARD_SAFE(cache->all_triangles);
 
 	GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order);
+	DRW_TEXTURE_FREE_SAFE(cache->pos_in_order_tx);
 	GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order);
 	GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order);
 
@@ -1859,6 +1864,8 @@ static void mesh_batch_cache_clear(Mesh *me)
 	GWN_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency);
 	GWN_BATCH_DISCARD_SAFE(cache->edge_detection);
 
+	DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx);
+
 	GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
 	if (cache->shaded_triangles_in_order) {
 		for (int i = 0; i < cache->mat_len; ++i) {
@@ -2826,8 +2833,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
 		static Gwn_VertFormat format = { 0 };
 		static struct { uint pos, nor; } attr_id;
 		if (format.attrib_ct == 0) {
+			/* Normal is padded so that the vbo can be used as a buffer texture */
 			attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
-			attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+			attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
 		}
 
 		Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format);
@@ -2841,7 +2849,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
 			uint i;
 
 			BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
-				static short no_short[3];
+				static short no_short[4];
 				normal_float_to_short_v3(no_short, eve->no);
 
 				GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co);
@@ -2852,7 +2860,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order(
 		else {
 			for (int i = 0; i < vbo_len_capacity; ++i) {
 				GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co);
-				GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no);
+				GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); /* XXX actually reading 4 shorts */
 			}
 		}
 	}
@@ -3323,10 +3331,86 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
 	}
 
 	return cache->edges_adjacency;
-
 }
 #undef NO_EDGE
 
+static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+	BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
+
+	BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */
+
+	if (cache->edges_face_overlay_tx != NULL) {
+		return cache->edges_face_overlay_tx;
+	}
+
+	const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+	cache->is_manifold = true;
+
+	Gwn_VertFormat format = {0};
+	uint index_id = GWN_vertformat_attr_add(&format, "index", GWN_COMP_I32, 1, GWN_FETCH_INT);
+	Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+
+	int vbo_len_capacity = tri_len * 3;
+	GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+
+	int vidx = 0;
+
+	for (int i = 0; i < tri_len; i++) {
+		bool edge_is_real[3] = {false, false, false};
+
+		MEdge *medge = rdata->medge;
+		MLoop *mloop = rdata->mloop;
+		MLoopTri *mlt = rdata->mlooptri + i;
+
+		int j, j_next;
+		for (j = 2, j_next = 0; j_next < 3; j = j_next++) {
+			MEdge *ed = &medge[mloop[mlt->tri[j]].e];
+			unsigned int tri_edge[2]  = {mloop[mlt->tri[j]].v, mloop[mlt->tri[j_next]].v};
+
+			if (((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) ||
+			    ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0])))
+			{
+				edge_is_real[j] = true;
+			}
+		}
+
+		for (int e = 0; e < 3; ++e) {
+			/* Save if there is an edge or not inside the sign bit. */
+			int value = (int)mloop[mlt->tri[e]].v + 1; /* Int 0 cannot be signed */
+			value = (edge_is_real[e]) ? -value : value;
+			GWN_vertbuf_attr_set(vbo, index_id, vidx++, &value);
+		}
+	}
+
+	int vbo_len_used = vidx;
+
+	if (vbo_len_capacity != vbo_len_used) {
+		GWN_vertbuf_data_resize(vbo, vbo_len_used);
+	}
+
+	/* Upload data early because we need to create the texture for it. */
+	GWN_vertbuf_use(vbo);
+	cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo);
+	cache->edges_face_overlay_tri_count = vbo_len_used / 3;
+
+	return cache->edges_face_overlay_tx;
+}
+
+static GPUTexture *mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+	BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
+
+	if (cache->pos_in_order_tx == NULL) {
+		Gwn_VertBuf *pos_in_order = mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache);
+		GWN_vertbuf_use(pos_in_order); /* Upload early for buffer texture creation. */
+		cache->pos_in_order_tx = GPU_texture_create_buffer(GPU_R32F, pos_in_order->vbo_id);
+	}
+
+	return cache->pos_in_order_tx;
+}
+
 static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
 {
 	BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
@@ -3857,6 +3941,27 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold
 	return cache->edge_detection;
 }
 
+void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
+        Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
+{
+	MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+	if (cache->edges_face_overlay_tx == NULL || cache->pos_in_order_tx == NULL) {
+		const int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
+
+		MeshRenderData *rdata = mesh_render_data_create(me, options);
+
+		mesh_batch_cache_get_edges_overlay_texture_buf(rdata, cache);
+		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;
+	*face_indices = cache->edges_face_overlay_tx;
+	*verts_data = cache->pos_in_order_tx;
+}
+
 static void mesh_batch_cache_create_overlay_batches(Mesh *me)
 {
 	BLI_assert(me->edit_btmesh != NULL);



More information about the Bf-blender-cvs mailing list