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