I would like to try and implement instancing for drawing multiple versions of the same object at different positions in the scene - preferrably using just a single API call. My Windows laptop drivers are limited to OpenGL 3.0 (waiting for nVidia to release Opengl 3.1 or 3.2 drivers!).
In my engine, the instance data for the models is in the form of a model matrix which specifies position, scale and rotation (as you’d expect really). I have been waiting for nVidia to implement the ARB/EXT_Instanced_Arrays which would be ideal for me as this API uses a divisor to break up an array of model matricies into instance ‘chunks’. This is easy to implement (in theory) into the current engine which is GL 2.1 based.
However,the Instanced_arrays extension is not forth comming and is probably side-lined in favour of other methods. This is where I need help because I can’t see how to actually impelment ARB_Texture_Buffer_Objects or ARB_Uniform_Buffer_Objects to hold the instance data and use ARB_Draw_Instanced to render the object instances.
My understanding of ARB_Uniform_Buffer_Objects or ARB_Texture_Buffer_Objects is that GLSL shader version 140/150 is required, and this is a problem because:
- Requires a re-write of model shaders to conform to version 140
1b) Requires a re-architect of engine to remove fixed function uniforms and attributes for version 140 shader compatability
- GLSL version 140 requires a GL 3.1 / 3.2 context ? - latop currently limited to GL 3.0
Additionally, it’s not clear how to access the ‘instance’ data in the uniform buffer object. Using DrawElementsInstanced API I can ‘see’ the glInstanceID increamenting for each itteration and in the shader I can get access to the InstanceID. However, how am I to get the model matricies (instance data) in the correct order for my current frame? For example, If I have 1000 instances to render I can pack all these into 1 single UBO. Using view fustrum culling, I now want to render 50, for example, so now I need someway of telling the shaders to read the model matricies for the visible instances. How ? Do I need to create a new UBO each frame with just the visisble instances? This would indicate to me an overhead on the CPU as the list is built, memory copied, and then uploaded to GL.
In this scenareo, UBO are more desirable than Texture_Buffer_Objects as the uniform buffers are contant over all vertices and thus processed faster than a per pixel lookup into the TBO to read the modelmatricies (instance data) - although I suppose the TBO could be read in the vertex shader - but I don’t know if this is faster or slower than TBO lookups in the pixel shader.
What I need from you guys is the following:
- Am I correct about the GLSL version requirements and re-writing shaders ?
- Has anyone actually implemented instanced model rendering as I am trying to- if so what technique did you use?
- UBO is the way to go rather than TBO ?
- Do UBO buffers need to be populated every frame to contain a linear set of instance data. ie there is no way to ‘skip’ over instance data in the UBO for the visible set of instances.
- Opengl 3.1 context needed to use uniform blocks
- Re-write of application to support uniform blocks along with UBO extension ?
Any help would be appreciated!