Hey, Thanks for your replies. 

Sorry about the fairly long post here , my earlier post I wanted to keep things 
as generic as possible to avoid lengthy detail :)

My 10K objects of 200 vertices each are instances of a smaller set (say less 
than 500) of 'prototype" indexed meshes, each having 200 vertices as a 
tri-strip. These prototype meshes don't change. Each instance has a different 
world transform matrix. I indicated that about 10% or 1K of the objects would 
change per frame, typically that would be changing their transform matrix but 
could also change which static "prototype" mesh they refer to. I also have a 
per vertex alpha array I need to apply to each instance vertex, and a small 
number of other per-instance single valued parameters to be read by a vertex 
shader. 

There is a certain coherency in which objects change on a frame: if an object 
changes on frame N it will change for a continuous period of time, e.g. until 
frame N + 150 for (say) a 5 second anim at 30 fps. However any static object 
may become dynamic at any time; it's arbitrary. I considered having a "hash 
table" of VBOs, such that the likelihood of having to rebuild each static VBO 
is diminished, but having even 10% of objects changing per frame means some 
object they would likely hash to each VBO and thus most VBOs would require 
rebuilding.

FWIW, I expect the GPU to be vertex-bound, as the actual pixel coverage of all 
these objects combined is only about 30% of the display.

The obvious method (to me) is to render per instance, but...

a) I don't want to rely on hardware instancing), so have considered 
pseudo-instancing using vertex attributes. I'd just draw each instance with its 
own drawElements call. However, I thought this would duplicate the mem 
transfers for the instances that did not change on the current frame (i.e. the 
majority of instances) and also interrupt the GPU while setting new vertex 
attributes for each instance. i.e. effectively:


Code:

for instance in Objects:
glVertexAttrib() // set attributes per instance 
glDrawElements() // draws using either a single VBO or bank of VBOs




( could not figure out how to indent with bbcode, sorry :)

b) I also considered rendering the dynamic objects with pseudo-instancing, and 
the static ones via one large "baked instance" VBO  & drawElements call, but 
the problem is that any given object may switch from static to dynamic or 
vice-versa on  any frame, meaning that I'd have to rebuild the baked buffer per 
frame anyway.

c) So I then considered just baking the 10% changed objects (world transform, 
vertex alpha) on each frame, and updating them to the same big VBO with the 
unchanged objects). A single glDrawElements call could then render the entire 
set as a single concatenated tri-strip, provided I could somehow reject the 
tris forming the "sausage link" between instances in the vertex shader. There 
I'd need some kind of double buffering to avoid blocking while waiting for GL 
to be done rendering with the VBO. That led to my question about how best to 
update that single, big VBO.

d) Right now, I'm thinking a good way is to create one big static VBO (& IBO) 
for all 10K instances, and one smaller VBO/IBO for the dynamic subset. I'd 
render each instance with its own drawElements(), checking each to see if I 
should override the static VBO and use the dynamic one. When an object switches 
from dynamic to static, just keep rendering it as though dynamic. At periodic 
intervals, rebuild the entire static VBO (every 3 seconds ?) to reflect the 
dynamic VBO changes. At that time, all instances that change from dynamic to 
static during that 3-second period would now be rendered as static again. As 
pseudocode:



Code:

render() 
{
   bind_dynamic_VBO() // use VBO for 10% dynamic objects
   for instance in Objects:
       if dynamic (instance): 
            update_dynamic_VBO(instance);

   for instance in list_of_dynamic( Objects ):
   {
           glVertexAttrib() // set attributes per instance, including embedded 
world matrix for vertex shader
        glDrawElements() // Draw. Note also using a static VBO/IBO to get the 
"prototype" vertex xyz positions & indices, (not shown) 
   }

    // use VBO for static objects. Does rendering statics after dynamics help 
ensure GL driver doesn't block access to the dynamic VBO on next frame ?

   bind_static_VBO() 
   for instance in list_of_static( Objects ):
   {
       glVertexAttrib() // set attributes per instance, with baked world matrix 
transforms 
       glDrawElements() // Draw, using same static VBO/IBO to get the 
"prototype" vertex xyz positions & indices, (not shown)
   }

   // periodic static buffer update...
   if time_elapsed( 5.0 ):
        bind_static_VBO() // updating VBO for static objects 
        for instance in Objects:
          if dynamic_became_static(instance):
              {
                        update_static_VBO( instance )
                    clear_dynamic_became_static( instance ):
                    }
}






So d) is my best thought so far. 

Anyway, no matter what I choose, I'd still like to know if I should double 
buffer, either by glBufferData(0) or physically using two VBOs in a ping-pong 
scheme.

Cheers,
Chris

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=25728#25728





_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to