[Bf-blender-cvs] [c4c3951c4f] clay-engine: Initial implementation of instancing

Clément Foucault noreply at git.blender.org
Tue Jan 31 11:52:33 CET 2017


Commit: c4c3951c4f294a4c543a81cb6b06a68fda8e970a
Author: Clément Foucault
Date:   Tue Jan 31 02:12:24 2017 +0100
Branches: clay-engine
https://developer.blender.org/rBc4c3951c4f294a4c543a81cb6b06a68fda8e970a

Initial implementation of instancing

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

M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_mode_pass.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/gawain/batch.c
M	source/blender/gpu/gawain/batch.h
M	source/blender/gpu/intern/gpu_shader.c
A	source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl

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

diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 6d26f7b8b7..8bd3cabf8d 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -160,6 +160,7 @@ typedef enum {
 /* Used by DRWShadingGroup.dyntype */
 #define DRW_DYN_POINTS 1
 #define DRW_DYN_LINES 2
+#define DRW_DYN_INSTANCE 3
 
 DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
 void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 45c8b911df..9fc020885d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -90,6 +90,7 @@ struct DRWInterface {
 	int modelview;
 	int projection;
 	int modelviewprojection;
+	int viewprojection;
 	int normal;
 	int eye;
 };
@@ -114,6 +115,8 @@ struct DRWShadingGroup {
 	int state;                       /* State changes for this batch only */
 	short dyntype;                   /* Dynamic Batch type, 0 is normal */
 	Batch *dyngeom;                  /* Dynamic batch */
+	GLuint instance_vbo;             /* Dynamic batch VBO storing Model Matrices */
+	int instance_count;                /* Dynamic batch Number of instance to render */
 };
 
 /* Render State */
@@ -277,6 +280,7 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
 
 	interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix");
 	interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix");
+	interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix");
 	interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
 	interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
 	interface->eye = GPU_shader_get_uniform(shader, "eye");
@@ -440,16 +444,13 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const
 	DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1, 0);
 }
 
-static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
+/* Creates OGL primitives based on DRWCall.obmat position list */
+static void shgroup_dynamic_batch_primitives(DRWShadingGroup *shgroup)
 {
 	int i = 0;
 	int nbr = BLI_listbase_count(&shgroup->calls);
 	GLenum type;
 
-#ifdef WITH_VIEWPORT_CACHE_TEST
-	if (shgroup->dyngeom) return;
-#endif
-
 	if (nbr == 0) {
 		if (shgroup->dyngeom) {
 			Batch_discard(shgroup->dyngeom);
@@ -491,6 +492,67 @@ static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
 	MEM_freeN(data);
 }
 
+static void shgroup_dynamic_batch_instance(DRWShadingGroup *shgroup)
+{
+	int i = 0;
+	int nbr = BLI_listbase_count(&shgroup->calls);
+
+	shgroup->instance_count = nbr;
+
+	if (nbr == 0) {
+		if (shgroup->instance_vbo) {
+			glDeleteBuffers(1, &shgroup->instance_vbo);
+			shgroup->instance_vbo = 0;
+		}
+		return;
+	}
+
+	/* Gather Data */
+	float *data = MEM_mallocN(sizeof(float) * 4 * 4 * nbr , "Instance Model Matrix");
+
+	for (DRWCall *call = shgroup->calls.first; call; call = call->next, i++) {
+		copy_m4_m4(&data[i*16], call->obmat);
+	}
+
+	/* Upload Data */
+	static VertexFormat format = { 0 };
+	static unsigned mat_id;
+	if (format.attrib_ct == 0) {
+		mat_id = add_attrib(&format, "InstanceModelMatrix", GL_FLOAT, 4, KEEP_FLOAT);
+	}
+
+	VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+	VertexBuffer_allocate_data(vbo, nbr);
+
+	fillAttrib(vbo, mat_id, data);
+
+	/* TODO poke mike to add this to gawain */
+	if (shgroup->instance_vbo) {
+		glDeleteBuffers(1, &shgroup->instance_vbo);
+		shgroup->instance_vbo = 0;
+	}
+
+	glGenBuffers(1, &shgroup->instance_vbo);
+	glBindBuffer(GL_ARRAY_BUFFER, shgroup->instance_vbo);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4 * nbr, data, GL_STATIC_DRAW);
+
+	MEM_freeN(data);
+}
+
+static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
+{
+#ifdef WITH_VIEWPORT_CACHE_TEST
+	if (shgroup->dyngeom) return;
+#endif
+
+	if (shgroup->dyntype == DRW_DYN_INSTANCE) {
+		shgroup_dynamic_batch_instance(shgroup);
+	}
+	else {
+		shgroup_dynamic_batch_primitives(shgroup);
+	}
+}
+
 /* ***************************************** PASSES ******************************************/
 
 DRWPass *DRW_pass_create(const char *name, DRWState state)
@@ -593,7 +655,8 @@ typedef struct DRWBoundTexture {
 	GPUTexture *tex;
 } DRWBoundTexture;
 
-static void draw_geometry(DRWShadingGroup *shgroup, DRWInterface *interface, Batch *geom, const float (*obmat)[4])
+static void draw_geometry(DRWShadingGroup *shgroup, DRWInterface *interface, Batch *geom,
+                          unsigned int instance_vbo, int instance_count, const float (*obmat)[4])
 {
 	RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
 	
@@ -629,6 +692,9 @@ static void draw_geometry(DRWShadingGroup *shgroup, DRWInterface *interface, Bat
 	if (interface->modelviewprojection != -1) {
 		GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
 	}
+	if (interface->viewprojection != -1) {
+		GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)rv3d->persmat);
+	}
 	if (interface->projection != -1) {
 		GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat);
 	}
@@ -644,7 +710,12 @@ static void draw_geometry(DRWShadingGroup *shgroup, DRWInterface *interface, Bat
 
 	/* step 2 : bind vertex array & draw */
 	Batch_set_program(geom, GPU_shader_get_program(shgroup->shader));
-	Batch_draw_stupid(geom);
+	if (instance_vbo) {
+		Batch_draw_stupid_instanced(geom, instance_vbo, instance_count);
+	}
+	else {
+		Batch_draw_stupid(geom);
+	}
 }
 
 static void draw_shgroup(DRWShadingGroup *shgroup)
@@ -714,13 +785,21 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
 		/* Replacing multiple calls with only one */
 		float obmat[4][4];
 		unit_m4(obmat);
-		/* Some dynamic batch can have no geom (no call to aggregate) */
-		if (shgroup->dyngeom)
-			draw_geometry(shgroup, interface, shgroup->dyngeom, obmat);
+
+		if (shgroup->dyntype == DRW_DYN_INSTANCE) {
+			DRWCall *call = shgroup->calls.first;
+			draw_geometry(shgroup, interface, call->geometry, shgroup->instance_vbo, shgroup->instance_count, obmat);
+		}
+		else {
+			/* Some dynamic batch can have no geom (no call to aggregate) */
+			if (shgroup->dyngeom) {
+				draw_geometry(shgroup, interface, shgroup->dyngeom, 0, 1, obmat);
+			}
+		}
 	}
 	else {
 		for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
-			draw_geometry(shgroup, interface, call->geometry, call->obmat);
+			draw_geometry(shgroup, interface, call->geometry, 0, 1, call->obmat);
 		}
 	}
 }
diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c
index 202921437c..d8db13925f 100644
--- a/source/blender/draw/intern/draw_mode_pass.c
+++ b/source/blender/draw/intern/draw_mode_pass.c
@@ -60,6 +60,7 @@ void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPa
 		*non_meshes = DRW_pass_create("Non Meshes Pass", state);
 
 		GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+		GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE);
 
 		/* Solid Wires */
 		grp = DRW_shgroup_create(sh, *non_meshes);
@@ -67,8 +68,15 @@ void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPa
 		/* Points */
 		grp = DRW_shgroup_create(sh, *non_meshes);
 
+		/* Empties */
+		static float frontcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+		grp = DRW_shgroup_create(sh_inst, *non_meshes);
+		DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
+		DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+
 		/* Stipple Wires */
 		grp = DRW_shgroup_create(sh, *non_meshes);
+		DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
 		DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2);
 
 		grp = DRW_shgroup_create(sh, *non_meshes);
@@ -214,8 +222,6 @@ void DRW_draw_lamp(DRWPass *non_meshes, Object *ob)
 void DRW_shgroup_non_meshes(DRWPass *non_meshes, Object *ob)
 {
 	struct Batch *geom;
-	static float frontcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-	GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
 
 	switch (ob->type) {
 		case OB_LAMP:
@@ -223,8 +229,7 @@ void DRW_shgroup_non_meshes(DRWPass *non_meshes, Object *ob)
 		case OB_EMPTY:
 		default:
 			geom = DRW_cache_plain_axes_get();
-			DRWShadingGroup *grp = DRW_pass_nth_shgroup_get(non_meshes, 0);
-			DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
+			DRWShadingGroup *grp = DRW_pass_nth_shgroup_get(non_meshes, 2);
 			DRW_shgroup_call_add(grp, geom, ob->obmat);
 			break;
 	}
@@ -234,7 +239,7 @@ void DRW_shgroup_relationship_lines(DRWPass *non_meshes, Object *ob)
 {
 	if (ob->parent) {
 		struct Batch *geom = DRW_cache_single_vert_get();
-		DRWShadingGroup *grp = DRW_pass_nth_shgroup_get(non_meshes, 5);
+		DRWShadingGroup *grp = DRW_pass_nth_shgroup_get(non_meshes, 6);
 		DRW_shgroup_call_add(grp, geom, ob->obmat);
 		DRW_shgroup_call_add(grp, geom, ob->parent->obmat);
 	}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 0f2e436026..7aeb67a224 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -148,6 +148,7 @@ data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_instance_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index dcd9b0fa9c..8cc9433c6a 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -108,6 +108,7 @@ typedef enum GPUBuiltinShader {
 	GPU_SHADER_2D_IMAGE_COLOR,
 	/* for simple 3D drawing */
 	GPU_SHADER_3D_UNIFORM_COLOR,
+	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list