Gawain: Add support for rendering using an instance batch (for particles)
This commit is contained in:
@@ -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*);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user