1
votes

Assuming I only want to render quads and can reuse my mesh, I would like to be able to, in a single draw call, render many instances.

I would like to achieve this with a texture buffer object by placing transformation matrices into the buffer.

I understand how to setup a texture buffer object in C++, but am confused on how to grab my transformations from this in GLSL.

uniform samplerBuffer sampler;
...
... = texelFetch( sampler, index );

In the above code (in a vertex shader) I'm not sure how the samplerBuffer keyword works (and have had a lot of trouble finding documentation). I would like to know which index in the texture buffer a given vertex is associated with, this way a transformation lookup can occur. How can I do this, and what would the GLSL syntax look like?

It can be assumed that the transformation matrices are 4x4 matrices. I was hoping to be able to keep the OpenGL version requirements in the 2.XX range.

Edit: So I found this: http://www.opengl.org/registry/specs/ARB/draw_instanced.txt. I can deal with a 3.0 limitation. However I'm getting confused when looking up examples of how to use this. Using GLEW, I suppose I would call glDrawElementsInstanced, but some places on the internet are saying this requires OpenGL version 3.3 or later. How can I take advantage of the 3.0 requirement I linked?

2
You can also use Uniform buffers which are much more suitable for multiple vector and matrix blocks upload. - Michael IV

2 Answers

3
votes

Well, a buffer texture is essentially a 1D array of data stored in a buffer object's (TEXTURE_BUFFER) data store. You provide a single integer, which is essentially an offset into the buffer and fetch a single texel with texelFetch starting at that offset. The offset always refers to a texel, not to a single component (e.g. the R-component of a vec4) of a texel. Therefore, if you setup the buffer texture with an internal format GL_R, you'll look up a single texel which only stores a single value - however, if you're using GL_RGBA a texel will consist of four components.

For instance, suppose you choose to put two normalized color vectors with RGBA components into the data store, choose the internal format GL_RGBA and index with 0 and 1, you'll get the first and the second texel from the buffer texture, as per section 8.9 of the core OpenGL 4.4 spec:

[..]the attached buffer object’s data store is interpreted as an array of elements of the GL data type corresponding to internalformat. Each texel consists of one to four elements that are mapped to texture components (R, G, B, and A).

Note that texelFetch will always return a gvec4, that is, an ivec4, uivec4 or vec4 depending on the internal format. If you choose an internal format which specifies less than four components, for instance GL_R32F, the result will be an unnormalized (<- that's important!) vec4(R, 0, 0, 1) - the remaining GB components are set to zero and A to 1. See table 8.15 of the aforementioned spec for a complete overview.

Also note that texelFetch does not perform any filtering or LOD clamping.

2
votes

All versions of texelFetch returns gvec4 so I assume you should perform a 4 lookups, 1 for each row. But that depends on how you encoded your matrix.

uniform samplerBuffer sampler;
...
mat4 transform( texelFetch( sampler, RowIndex0 ), texelFetch( sampler, RowIndex1 ), texelFetch( sampler, RowIndex2 ), texelFetch( sampler, RowIndex3 ) ); 

Keep in mind that mat4 in GLSL takes columns in the constructor, so you need to transpose that if you are working with Column based matrices.