I have the following setup:
S
- the scene that includes terrain, some houses and other man-made objectsT
- a set of tree configurations that I would like to iterate through and place inS
.
Every iteration results in a configuration C(i) = S + T(i)
that is rendered onto the screen.
Since S
is static and does not change between iterations I decided to employ glBufferSubData()
with a large buffer split into two regions, where the first region of my buffer will store S
, while the second region will contain the T(i)
. With every new iteration a new C(i)
will be the state of the big buffer.
This will allow me to pre-allocate the big buffer, except for one issue I am facing, namely that T(i)
may have slight variations in size. In order to not have to expand my buffer (e.g. through buffer orphaning aka buffer re-specification) I would like to pre-calculate the largest T(i)
resulting in a T_max
, which I can then use to calculate the total size of my big buffer as C_max = S + T_max
.
I know that glBufferSubData
allows a partial update of the data. The problem is that after my second region is updated with some T(i)
I may have old data remaining from T(i-j)
if the size of T(i)
is LESS THAN the size of T(i-j)
.
In this case I will have C(i,j) = S + T(i) + partial(T(i-j))
.
I was thinking that in this case I can calculate the offset of the partial data from T(i-j)
and use a second glBufferSubData()
that will set that chunk of memory to NULL
or actual 0
(see bullet points below). So I will have
[ S ][ T(i) ][ NULLs/0s ]
I read that for
- VBOs this is not really an issue
- IBOs this may lead to
- Ignore the index and continue processing (most likely scenario)
- Restart the primitive being drawn (potentially causing rendering artifacts)
- In rare cases, it could lead to a program crash
- UBOs (which I am not using here, at least yet) this may lead to
- For numeric data types (float, int, etc.), NULL values will likely be interpreted as zeros
- For data types like vec3 or mat4 (representing vectors or matrices), NULL might be treated as all zeros, leading to unexpected behavior in the shader.
I am curious what exactly happens under the hood and how to avoid crashes. My hope is that this is not yet another "it depends on the driver implementation" scenario. :D
BufferData
instead ofBufferSubData
(always a fresh buffer for T of the desired size). Recommended: khronos.org/opengl/wiki/Buffer_Object_StreamingglVertexAttribPointer
only specifies the format of the buffer (size and type of one element), not the amount of data/elements in the buffer. As long as you adjust the count parameter of the draw command(which you have to do anyway), there shouldn't be a problem.