Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-01-31 04:12:24 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-01-31 13:44:40 +0300
commitc4c3951c4f294a4c543a81cb6b06a68fda8e970a (patch)
tree91342d8534810f0272ec27fe18e0c8f616dbe5ea
parent75d6a30cc2fc25c43f77259822853161d19418ac (diff)
Initial implementation of instancing
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_manager.c101
-rw-r--r--source/blender/draw/intern/draw_mode_pass.c15
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_shader.h1
-rw-r--r--source/blender/gpu/gawain/batch.c51
-rw-r--r--source/blender/gpu/gawain/batch.h1
-rw-r--r--source/blender/gpu/intern/gpu_shader.c2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl10
9 files changed, 167 insertions, 16 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 6d26f7b8b7e..8bd3cabf8de 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 45c8b911df1..9fc020885da 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 202921437c0..d8db13925fc 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 0f2e4360263..7aeb67a224d 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 dcd9b0fa9c8..8cc9433c6ab 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,
+ GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
GPU_SHADER_3D_FLAT_COLOR,
GPU_SHADER_3D_SMOOTH_COLOR,
GPU_SHADER_3D_DEPTH_ONLY,
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c
index df7733d70dc..99c13301177 100644
--- a/source/blender/gpu/gawain/batch.c
+++ b/source/blender/gpu/gawain/batch.c
@@ -282,3 +282,54 @@ void Batch_draw_stupid(Batch* batch)
// Batch_done_using_program(batch);
glBindVertexArray(0);
}
+
+/* clement : temp stuff */
+void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count)
+{
+ if (batch->vao_id)
+ glBindVertexArray(batch->vao_id);
+ else
+ Batch_prime(batch);
+
+ if (batch->program_dirty)
+ Batch_update_program_bindings(batch);
+
+ const GLint loc = glGetAttribLocation(batch->program, "InstanceModelMatrix");
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
+ glEnableVertexAttribArray(loc);
+ glVertexAttribPointer(loc + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)0);
+ glEnableVertexAttribArray(loc + 1);
+ glVertexAttribPointer(loc + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(sizeof(float)*4));
+ glEnableVertexAttribArray(loc + 2);
+ glVertexAttribPointer(loc + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(2 * sizeof(float)*4));
+ glEnableVertexAttribArray(loc + 3);
+ glVertexAttribPointer(loc + 3, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(3 * sizeof(float)*4));
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glVertexAttribDivisor(loc + 0, 1);
+ glVertexAttribDivisor(loc + 1, 1);
+ glVertexAttribDivisor(loc + 2, 1);
+ glVertexAttribDivisor(loc + 3, 1);
+
+ // Batch_use_program(batch);
+
+ //gpuBindMatrices(batch->program);
+
+ if (batch->elem)
+ {
+ const ElementList* el = batch->elem;
+
+ glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
+ }
+ else
+ glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count);
+
+ // Batch_done_using_program(batch);
+ glBindVertexArray(0);
+}
+
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
index 3db910151d9..8b5c48cca79 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/source/blender/gpu/gawain/batch.h
@@ -58,6 +58,7 @@ void Batch_Uniform4fv(Batch*, const char* name, const float data[4]);
void Batch_draw(Batch*);
void Batch_draw_stupid(Batch* batch);
+void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 7dcb3796f75..6370e4f7f8c 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -65,6 +65,7 @@ extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_instance_vert_glsl[];
extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
@@ -670,6 +671,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE] = { datatoc_gpu_shader_3D_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
[GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl
new file mode 100644
index 00000000000..7eb321f2996
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl
@@ -0,0 +1,10 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+in vec3 pos;
+in mat4 InstanceModelMatrix;
+
+void main()
+{
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
+}