[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