Gawain: Add support for rendering using an instance batch (for particles)

This commit is contained in:
2017-05-29 16:28:54 +02:00
parent 97e89027fc
commit ec90780767
4 changed files with 76 additions and 20 deletions

View File

@@ -73,7 +73,7 @@ void Batch_draw(Batch*);
void Batch_draw_stupid(Batch*);
void Batch_draw_stupid_instanced(Batch*, unsigned int instance_vbo, int instance_count,
int attrib_nbr, int attrib_stride, int attrib_loc[16], int attrib_size[16]);
void Batch_draw_stupid_instanced_with_batch(Batch*, Batch*);

View File

@@ -374,3 +374,69 @@ void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int in
// Batch_done_using_program(batch);
glBindVertexArray(0);
}
void Batch_draw_stupid_instanced_with_batch(Batch* batch_instanced, Batch* batch_instancing)
{
if (batch_instanced->vao_id)
glBindVertexArray(batch_instanced->vao_id);
else
Batch_prime(batch_instanced);
if (batch_instanced->program_dirty)
Batch_update_program_bindings(batch_instanced);
VertexBuffer* verts = batch_instancing->verts[0];
const VertexFormat* format = &verts->format;
const unsigned attrib_ct = format->attrib_ct;
const unsigned stride = format->stride;
VertexBuffer_use(verts);
for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx)
{
const Attrib* a = format->attribs + a_idx;
const GLvoid* pointer = (const GLubyte*)0 + a->offset;
for (unsigned n_idx = 0; n_idx < a->name_ct; ++n_idx)
{
const ShaderInput* input = ShaderInterface_attrib(batch_instanced->interface, a->name[n_idx]);
if (input == NULL) continue;
glEnableVertexAttribArray(input->location);
glVertexAttribDivisor(input->location, 1);
switch (a->fetch_mode)
{
case KEEP_FLOAT:
case CONVERT_INT_TO_FLOAT:
glVertexAttribPointer(input->location, a->comp_ct, a->gl_comp_type, GL_FALSE, stride, pointer);
break;
case NORMALIZE_INT_TO_FLOAT:
glVertexAttribPointer(input->location, a->comp_ct, a->gl_comp_type, GL_TRUE, stride, pointer);
break;
case KEEP_INT:
glVertexAttribIPointer(input->location, a->comp_ct, a->gl_comp_type, stride, pointer);
}
}
}
// Batch_use_program(batch);
//gpuBindMatrices(batch->program);
if (batch_instanced->elem)
{
const ElementList* el = batch_instanced->elem;
glDrawElementsInstanced(batch_instanced->gl_prim_type, el->index_ct, GL_UNSIGNED_INT, 0, verts->vertex_ct);
}
else
glDrawArraysInstanced(batch_instanced->gl_prim_type, 0, batch_instanced->verts[0]->vertex_ct, verts->vertex_ct);
// Batch_done_using_program(batch);
glBindVertexArray(0);
}

View File

@@ -1133,18 +1133,11 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
DRWInterface *interface = shgroup->interface;
int buffer_size = 0;
/* XXX All of this is pretty garbage. Better revisit it later. */
if (interface->instance_batch != NULL) {
VertexBuffer *vert = interface->instance_batch->verts[0];
/* This is double check but we don't want
* VertexBuffer_use() to bind the buffer if it exists. */
if (vert->vbo_id == 0) {
VertexBuffer_use(vert);
}
interface->instance_vbo = vert->vbo_id;
interface->instance_count = vert->vertex_ct;
return;
}
/* TODO We still need this because gawain does not support Matrix attribs. */
if (interface->instance_count == 0) {
if (interface->instance_vbo) {
glDeleteBuffers(1, &interface->instance_vbo);
@@ -1163,11 +1156,6 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
}
}
if (interface->instance_batch != NULL) {
/* Quit just after attribs where specified */
return;
}
/* Gather Data */
buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
float *data = MEM_mallocN(buffer_size, "Instance VBO data");
@@ -1611,7 +1599,10 @@ 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) {
if (interface->instance_batch) {
Batch_draw_stupid_instanced_with_batch(geom, interface->instance_batch);
}
else if (interface->instance_vbo) {
Batch_draw_stupid_instanced(geom, interface->instance_vbo, interface->instance_count, interface->attribs_count,
interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
}
@@ -1737,7 +1728,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
float obmat[4][4];
unit_m4(obmat);
if (shgroup->type == DRW_SHG_INSTANCE && interface->instance_count > 0) {
if (shgroup->type == DRW_SHG_INSTANCE &&
(interface->instance_count > 0 || interface->instance_batch != NULL))
{
GPU_SELECT_LOAD_IF_PICKSEL_LIST(&shgroup->calls);
draw_geometry(shgroup, shgroup->instance_geom, obmat, NULL);
}

View File

@@ -1486,9 +1486,6 @@ static void OBJECT_cache_populate_particles(Object *ob,
if (shgrp) {
if (draw_as != PART_DRAW_DOT) {
DRW_shgroup_attrib_float(shgrp, "pos", 3);
DRW_shgroup_attrib_float(shgrp, "rot", 4);
DRW_shgroup_attrib_float(shgrp, "val", 1);
DRW_shgroup_uniform_short_to_int(shgrp, "draw_size", &part->draw_size, 1);
DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_instance_batch(shgrp, geom);