[Bf-blender-cvs] [5ae58f8ab88] blender2.8: DWM: Use draw manager for sculpt PBVH drawing

Campbell Barton noreply at git.blender.org
Thu May 11 13:29:42 CEST 2017


Commit: 5ae58f8ab889abfc8a1c8d9538ae0b4dea989408
Author: Campbell Barton
Date:   Thu May 11 21:21:59 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB5ae58f8ab889abfc8a1c8d9538ae0b4dea989408

DWM: Use draw manager for sculpt PBVH drawing

Add a shader-group type to draw
generated geometry by running a callback.

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

M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/pbvh.c
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/modes/sculpt_mode.c
M	source/blender/gpu/GPU_buffers.h
M	source/blender/gpu/intern/gpu_buffers.c

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

diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 927303f8b3c..53180713cf9 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -30,6 +30,7 @@
 #include "BLI_ghash.h"
 #include "BLI_utildefines.h"
 
+struct Batch;
 struct CCGElem;
 struct CCGKey;
 struct CustomData;
@@ -118,6 +119,9 @@ void BKE_pbvh_raycast_project_ray_root(
 void BKE_pbvh_node_draw(PBVHNode *node, void *data);
 void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
                    int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
+void BKE_pbvh_draw_cb(
+        PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+        void (*draw_fn)(void *user_data, struct Batch *batch), void *user_data);
 
 /* PBVH Access */
 typedef enum {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 6bfb9d779c2..02b4479df4f 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1845,6 +1845,67 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3],
 		pbvh_draw_BB(bvh);
 }
 
+struct PBVHNodeDrawCallbackData {
+
+	void (*draw_fn)(void *user_data, Batch *batch);
+	void *user_data;
+	bool fast;
+};
+
+static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
+{
+	struct PBVHNodeDrawCallbackData *data = data_v;
+
+	if (!(node->flag & PBVH_FullyHidden)) {
+		Batch *triangles = GPU_draw_pbvh_buffers_get_batch(node->draw_buffers, data->fast);
+		if (triangles != NULL) {
+			data->draw_fn(data->user_data, triangles);
+		}
+	}
+}
+
+/**
+ * Version of #BKE_pbvh_draw that runs a callback.
+ */
+void BKE_pbvh_draw_cb(
+        PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+        void (*draw_fn)(void *user_data, Batch *batch), void *user_data)
+{
+	struct PBVHNodeDrawCallbackData draw_data = {
+		.fast = fast,
+		.draw_fn = draw_fn,
+		.user_data = user_data,
+	};
+	PBVHNode **nodes;
+	int totnode;
+
+	for (int a = 0; a < bvh->totnode; a++)
+		pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
+
+	BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
+	                       &nodes, &totnode);
+
+	pbvh_update_normals(bvh, nodes, totnode, fnors);
+	pbvh_update_draw_buffers(bvh, nodes, totnode);
+
+	if (nodes) MEM_freeN(nodes);
+
+	if (planes) {
+		BKE_pbvh_search_callback(
+		        bvh, BKE_pbvh_node_planes_contain_AABB,
+		        planes, pbvh_node_draw_cb, &draw_data);
+	}
+	else {
+		BKE_pbvh_search_callback(
+		        bvh, NULL,
+		        NULL, pbvh_node_draw_cb, &draw_data);
+	}
+#if 0
+	if (G.debug_value == 14)
+		pbvh_draw_BB(bvh);
+#endif
+}
+
 void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
                            DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
 {
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 1cdb213d86f..bcc3277adc9 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -254,6 +254,7 @@ typedef enum {
 
 
 DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_create_fn(struct GPUShader *shader, DRWPass *pass);
 DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
 DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material, DRWPass *pass, struct Batch *geom);
 DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Batch *geom);
@@ -261,8 +262,15 @@ DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPas
 DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
 DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size);
 
+typedef void (DRWCallGenerateFn)(
+        DRWShadingGroup *shgroup,
+        void (*draw_fn)(DRWShadingGroup *shgroup, struct Batch *geom),
+        void *user_data);
+
 void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
 void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_call_generate_add(
+        DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]);
 void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len);
 #define DRW_shgroup_call_dynamic_add(shgroup, ...) do { \
 	const void *array[] = {__VA_ARGS__}; \
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index df3b4d03d8b..33456e20163 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -189,10 +189,21 @@ typedef struct DRWCall {
 #ifdef USE_GPU_SELECT
 	int select_id;
 #endif
-	Batch *geometry;
 	float (*obmat)[4];
+	Batch *geometry;
 } DRWCall;
 
+typedef struct DRWCallGenerate {
+	struct DRWCallGenerate *next, *prev;
+#ifdef USE_GPU_SELECT
+	int select_id;
+#endif
+	float (*obmat)[4];
+
+	DRWCallGenerateFn *geometry_fn;
+	void *user_data;
+} DRWCallGenerate;
+
 typedef struct DRWCallDynamic {
 	struct DRWCallDynamic *next, *prev;
 #ifdef USE_GPU_SELECT
@@ -222,6 +233,8 @@ struct DRWShadingGroup {
 /* Used by DRWShadingGroup.type */
 enum {
 	DRW_SHG_NORMAL,
+	/* same as 'DRW_SHG_NORMAL' but use a callback to generate geometry */
+	DRW_SHG_NORMAL_GENERATE,
 	DRW_SHG_POINT_BATCH,
 	DRW_SHG_LINE_BATCH,
 	DRW_SHG_TRIANGLE_BATCH,
@@ -646,6 +659,15 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
 	return shgroup;
 }
 
+DRWShadingGroup *DRW_shgroup_create_fn(struct GPUShader *shader, DRWPass *pass)
+{
+	DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
+
+	shgroup->type = DRW_SHG_NORMAL_GENERATE;
+
+	return shgroup;
+}
+
 DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass)
 {
 	double time = 0.0; /* TODO make time variable */
@@ -796,6 +818,28 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[
 	BLI_addtail(&shgroup->calls, call);
 }
 
+void DRW_shgroup_call_generate_add(
+        DRWShadingGroup *shgroup,
+        DRWCallGenerateFn *geometry_fn, void *user_data,
+        float (*obmat)[4])
+{
+	BLI_assert(geometry_fn != NULL);
+	BLI_assert(shgroup->type == DRW_SHG_NORMAL_GENERATE);
+
+	DRWCallGenerate *call = MEM_callocN(sizeof(DRWCallGenerate), "DRWCallGenerate");
+
+	call->obmat = obmat;
+
+	call->geometry_fn = geometry_fn;
+	call->user_data = user_data;
+
+#ifdef USE_GPU_SELECT
+	call->select_id = g_DRW_select_id;
+#endif
+
+	BLI_addtail(&shgroup->calls, call);
+}
+
 void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *attr[], unsigned int attr_len)
 {
 	DRWInterface *interface = shgroup->interface;
@@ -1348,7 +1392,7 @@ typedef struct DRWBoundTexture {
 	GPUTexture *tex;
 } DRWBoundTexture;
 
-static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4])
+static void draw_geometry_prepare(DRWShadingGroup *shgroup, const float (*obmat)[4])
 {
 	RegionView3D *rv3d = DST.draw_ctx.rv3d;
 	DRWInterface *interface = shgroup->interface;
@@ -1445,7 +1489,11 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
 	if (interface->eye != -1) {
 		GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
 	}
+}
 
+static void draw_geometry_execute(DRWShadingGroup *shgroup, Batch *geom)
+{
+	DRWInterface *interface = shgroup->interface;
 	/* step 2 : bind vertex array & draw */
 	Batch_set_program(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
 	if (interface->instance_vbo) {
@@ -1457,6 +1505,13 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
 	}
 }
 
+static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4])
+{
+	draw_geometry_prepare(shgroup, obmat);
+
+	draw_geometry_execute(shgroup, geom);
+}
+
 static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 {
 	BLI_assert(shgroup->shader);
@@ -1472,7 +1527,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 		DST.shader = shgroup->shader;
 	}
 
-	if (shgroup->type != DRW_SHG_NORMAL) {
+	const bool is_normal = ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_NORMAL_GENERATE);
+
+	if (!is_normal) {
 		shgroup_dynamic_batch_from_calls(shgroup);
 	}
 
@@ -1547,7 +1604,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 #endif
 
 	/* Rendering Calls */
-	if (shgroup->type != DRW_SHG_NORMAL) {
+	if (!is_normal) {
 		/* Replacing multiple calls with only one */
 		float obmat[4][4];
 		unit_m4(obmat);
@@ -1564,7 +1621,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 			}
 		}
 	}
-	else {
+	else if (shgroup->type == DRW_SHG_NORMAL) {
 		for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
 			bool neg_scale = call->obmat && is_negative_m4(call->obmat);
 
@@ -1582,6 +1639,29 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 			}
 		}
 	}
+	else if (shgroup->type == DRW_SHG_NORMAL_GENERATE) {
+		/* Same as 'DRW_SHG_NORMAL' but generate batches */
+		for (DRWCallGenerate *call = shgroup->calls.first; call; call = call->next) {
+			bool neg_scale = call->obmat && is_negative_m4(call->obmat);
+
+			/* Negative scale objects */
+			if (neg_scale) {
+				glFrontFace(GL_CW);
+			}
+
+			GPU_SELECT_LOAD_IF_PICKSEL(call);
+			draw_geometry_prepare(shgroup, call->obmat);
+			call->geometry_fn(shgroup, draw_geometry_execute, call->user_data);
+
+			/* Reset state */
+			if (neg_scale) {
+				glFrontFace(GL_CCW);
+			}
+		}
+	}
+	else {
+		BLI_assert(0);
+	}
 
 	/* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
 	DRW_state_reset();
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index 114bc8c96c4..ba9219c9abb 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/s

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list