X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Finstancearray.cpp;h=abd9fcd0bd870d14def0192392490b09c702fa2d;hp=4156c6f37101fec121244444370af8ff55202faf;hb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;hpb=b0059bd068c99dadfc922584911fcb25a21b737b diff --git a/source/instancearray.cpp b/source/instancearray.cpp index 4156c6f3..abd9fcd0 100644 --- a/source/instancearray.cpp +++ b/source/instancearray.cpp @@ -24,13 +24,29 @@ InstanceArray::InstanceArray(const Object &o): instance_data(0), instance_buffer(0), vtx_setup(0), + matrix_location(-1), matrix_offset(0) { + const Technique *tech = object.get_technique(); + const Technique::PassMap &passes = tech->get_passes(); + for(Technique::PassMap::const_iterator i=passes.begin(); i!=passes.end(); ++i) + { + const Program *shprog = i->second.get_shader_program(); + if(!shprog) + throw invalid_argument("InstanceArray::InstanceArray"); + + int loc = shprog->get_attribute_location("instance_transform"); + if(matrix_location<0) + matrix_location = loc; + else if(loc!=matrix_location) + throw invalid_argument("InstanceArray::InstanceArray"); + } + if(ARB_vertex_array_object && ARB_instanced_arrays && ARB_draw_instanced) { - instance_data = new VertexArray((ATTRIB4,12, ATTRIB4,13, ATTRIB4,14)); + instance_data = new VertexArray((ATTRIB4,matrix_location, ATTRIB4,matrix_location+1, ATTRIB4,matrix_location+2)); const VertexFormat &fmt = instance_data->get_format(); - matrix_offset = fmt.offset(make_indexed_component(ATTRIB4, 12)); + matrix_offset = fmt.offset(make_indexed_component(ATTRIB4, matrix_location)); instance_buffer = new Buffer(ARRAY_BUFFER); instance_data->use_buffer(instance_buffer); @@ -46,6 +62,8 @@ InstanceArray::InstanceArray(const Object &o): InstanceArray::~InstanceArray() { + for(std::vector::iterator i=instances.begin(); i!=instances.end(); ++i) + delete *i; delete vtx_setup; delete instance_data; delete instance_buffer; @@ -57,7 +75,16 @@ void InstanceArray::append(ObjectInstance *inst) if(instance_data) { if(instance_data->size()append(); + unsigned req_size = instance_data->get_required_buffer_size(); + if(instance_buffer->get_size()>0 && instance_buffer->get_size()use_buffer(instance_buffer); + } + } update_instance_matrix(instances.size()-1); } } @@ -95,16 +122,18 @@ void InstanceArray::render(Renderer &renderer, const Tag &tag) const const Technique *tech = object.get_technique(); if(!tech) throw logic_error("no technique"); - if(!tech->has_pass(tag)) + const RenderPass *pass = tech->find_pass(tag); + if(!pass) return; - const RenderPass &pass = tech->get_pass(tag); const Mesh *mesh = object.get_mesh(); mesh->get_vertices().refresh(); + if(instance_buffer->get_size()==0) + instance_buffer->storage(instance_data->get_required_buffer_size()); instance_data->refresh(); Renderer::Push push(renderer); - pass.apply(renderer); + pass->apply(renderer); mesh->draw_instanced(renderer, *vtx_setup, instances.size()); } else @@ -112,9 +141,8 @@ void InstanceArray::render(Renderer &renderer, const Tag &tag) const for(vector::const_iterator i=instances.begin(); i!=instances.end(); ++i) { const Matrix &m = *(*i)->get_matrix(); - glVertexAttrib4f(12, m(0, 0), m(0, 1), m(0, 2), m(0, 3)); - glVertexAttrib4f(13, m(1, 0), m(1, 1), m(1, 2), m(1, 3)); - glVertexAttrib4f(14, m(2, 0), m(2, 1), m(2, 2), m(2, 3)); + for(unsigned j=0; j<3; ++j) + glVertexAttrib4f(matrix_location+j, m(j, 0), m(j, 1), m(j, 2), m(j, 3)); (*i)->render(renderer, tag); } }