Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: VBO Instancing - Attribute per Vertex per Instance

  1. #1
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    5

    VBO Instancing - Attribute per Vertex per Instance

    As I understand it, glDrawArraysInstanced() will draw a VBO n times.
    glVertexAttribDivisor() using 1, so that each instance has a unique attribute in the shader. So far I can pass a different color for each instance, with vec4*instances, and each vertex in that instance will share that attribute, hence each instance of a triangle has a different color.

    However, what I'm looking for is a type of divisor that will advance the attribute per vertex for each instance, and the best example would be a different color for each vertex in a triangle, for each instance. I would fill a VBO with 3*vec4*instances.

    Eg. I want to draw 2 triangles using instancing, I would assume to give the 3 colors per vertex for as many instances I am drawing:

    Code :
    color_vbo_data [] = {
        vec4, vec4, vec4, // first triangle's vertex colors
        vec4, vec4, vec4 // second triangle's vertex colors
    };
     
    glDrawArraysInstanced(GL_TRIANGLES, 0, 3(vertexes), 2(instances));

    If I set the attribute divisor to 0, it will use the first 3 colors of the color_vbo_data everywhere (so each triangle will have the first 3 colors in the VBO only), rather than advancing.
    Effectively each vertex should get the attribute from the VBO as if it were:

    Code :
    color_attribute = color_vbo[(vertex_count * current_instance) + current_vertex];
    Last edited by error17; 03-01-2014 at 05:24 AM.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    989
    You cannot do this using vertex attributes and the features provided by ARB_instanced_arrays.
    However, you *can* do it (and way more) using ARB_draw_instanced and ARB_texture_buffer_object.

    Before going forward, though, I'd like to clarify a few things:
    There is no such thing like "drawing a VBO". Draws are just draws that issue a certain number of primitives. Also, VBO is just a term that refers to using a buffer object as the source of vertex attribute information. But the same buffer can be used for other purposes too, like texture buffer access, etc.

    So the solution:
    Put your color data into a separate buffer object. Bind it as e.g. an RGBA8 texture buffer (if you store your color as 8-bit normalized RGBA values).
    Then, in your vertex shader, just fetch the appropriate color value as follows:
    Code :
    ...
    uniform samplerBuffer myTextureBuffer;
    ...
    void main() {
      ...
      color_attribute = texelFetch(myTextureBuffer, (gl_InstanceID * vertex_count) + gl_VertexID);
      ...
    }
    Please note a few things here:
    gl_InstanceID always gives you the currently processed instance's number, and gl_VertexID always gives you the currently processed vertex's number. These are built-in GLSL variables.
    Now for vertex_count, there is no built-in variable, thus you'll have to pass it e.g. as a uniform to the vertex shader.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  3. #3
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    5
    I guess that will have to do for now. I believe what I am trying to achieve is reasonable, I am quite disappointed that this has not been provided. That texture buffer solution is rather hackish and was hoping for an elegant solution, but as it seems, OpenGL is lacking some basic support for their instancing method.

    Thank you
    Last edited by error17; 03-01-2014 at 06:32 AM.

  4. #4
    Intern Contributor Brokenmind's Avatar
    Join Date
    Feb 2014
    Location
    Aachen / Germany
    Posts
    71
    One small addition: The texture solution is far from being a "hackish" solution. The uniform arrays have, depending on the graphics card, a very limited size over that the shader simply does not compile. I found the border being between 250 on better cards down to 170 on some, with each element being a vec4. With texturing, you can easily store millions of elements without experiencing any issues.

    On the other hand, it depends how you look at it: What is a texture more than a huge array of floating point values that you can display?

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    989
    Quote Originally Posted by error17 View Post
    I guess that will have to do for now. I believe what I am trying to achieve is reasonable, I am quite disappointed that this has not been provided. That texture buffer solution is rather hackish and was hoping for an elegant solution, but as it seems, OpenGL is lacking some basic support for their instancing method.
    That's the thing. The instanced arrays are the "hacky", old-style solution. Why have a set of fixed function features instead of one that is fully programmable?
    Using texture buffers, uniform buffers, or shader storage buffers and fetch from them arbitrarily using gl_VertexID and gl_InstanceID is a flexible, fully customizable solution. Using the vertex attrib divisor is just some old-style fixed function thing.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  6. #6
    Junior Member Newbie
    Join Date
    Mar 2014
    Posts
    5
    Hmm, I wasn't aware of that. I am fairly new to this modern OpenGL, seems like they should just make it even lower level and enable basic C style ideas. The name "Texture buffer" should instead be maybe called an array or something.

  7. #7
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,381
    Quote Originally Posted by aqnuep View Post
    The instanced arrays are the "hacky", old-style solution.
    Both are useful, but instance arrays can perform better than gl_InstanceID-style instancing, so I wouldn't write it off. Makes some sense as the GPU is pushing the right attributes into the shaders rather than waiting on the shaders to pull the correct attributes randomly from memory.
    Last edited by Dark Photon; 03-02-2014 at 01:34 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •