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 9 of 9

Thread: Vertex attributes - separated components

  1. #1
    Junior Member Newbie
    Join Date
    May 2017
    Location
    Czech Republic
    Posts
    8

    Question Vertex attributes - separated components

    Motivation:

    There are principally 2 basic ways how to organize vertex attributes in OpenGL buffers.

    1. Interleaved - for each vertex all attribute types are grouped together, example: (VNCVNCVNCVNCVNC)
    2. Separated - for each attribute type all vertices are grouped together, example: (VVVVVNNNNNCCCCC)

    Just for explanation - V stands for vertex position (coordinate vector), N stands for vertex normal (normal vector), C stands for vertex primary color (color vector). This description is used in OpenGL wiki article "Vertex Specification Best Practices" at https://www.khronos.org/opengl/wiki/...tting_VBO_Data.

    Question:

    Is it possible to reach such a level of vertex attribute separation where I can group even components of mentioned vectors together? In other words, I need to delivery to the OpenGL engine the x-components of all vertices as a continuous series first, followed by continuous series of y-components, etc. The reason is that I have got the raw data in that form and I don't want to rearrange it, as it is crazily expensive, naturally.

    Examples:
    (VxVxVxVxVxVyVyVyVyVyVzVzVzVzVzVwVwVwVwVw) - for each coordinate component [x,y,z,w] all vertices are grouped together
    (CrCrCrCrCrCgCgCgCgCgCbCbCbCbCbCaCaCaCaCa) - for each color component [r,g,b,a] all vertices are grouped together
    Last edited by Pivonka; 05-18-2017 at 12:01 AM.

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    460
    Just treat each vertex component as as much different attributes.
    For example, vertex attribute 0 will be vertex x, attribute 1 will be vertex y... and so on.

  3. #3
    Junior Member Newbie
    Join Date
    May 2017
    Location
    Czech Republic
    Posts
    8
    Thank you, Silence, I see what you mean ... in glVertexAttribPointer(), if I set size=1, stride=N (total # of vertices) and type to appropriate data type of my raw data, then it should work ...

    attr(0*N+0)=V0x, attr(0*N+1)=V1x, attr(0*N+2)=V2x, ...
    attr(1*N+0)=V0y, attr(1*N+1)=V1y, attr(1*N+2)=V2y, ...
    attr(2*N+0)=V0z, attr(2*N+1)=V1z, attr(2*N+2)=V2z, ...
    attr(3*N+0)=V0w, attr(3*N+1)=V1w, attr(3*N+2)=V2w, ...

    I just wonder, how it will look like on the data receiving party inside shaders ...

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,829
    Quote Originally Posted by Pivonka View Post
    Thank you, Silence, I see what you mean ... in glVertexAttribPointer(), if I set size=1, stride=N (total # of vertices)
    No. The stride will be the size of a single component. You will have as many attributes as components (i.e. 4 for the position, 3 for the normal, 4 for the colour, so 11 in total). If all components are in the same buffer, then each attribute will have an offset equal to the total size of all prior components. The data will be accessed in the vertex shader as 11 distinct "float" variables.

    IOW, something like
    Code :
    glBindBuffer(GL_ARRAY_BUFFER, position_buf);
    glVertexAttribPointer(glGetAttribLocation(pgm,"vx"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),0*nverts*4*sizeof(GLfloat));
    glVertexAttribPointer(glGetAttribLocation(pgm,"vy"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),1*nverts*4*sizeof(GLfloat));
    glVertexAttribPointer(glGetAttribLocation(pgm,"vz"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),2*nverts*4*sizeof(GLfloat));
    glVertexAttribPointer(glGetAttribLocation(pgm,"vw"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),3*nverts*4*sizeof(GLfloat));
    glBindBuffer(GL_ARRAY_BUFFER, normal_buf);
    glVertexAttribPointer(glGetAttribLocation(pgm,"nx"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),0*nverts*3*sizeof(GLfloat));
    glVertexAttribPointer(glGetAttribLocation(pgm,"ny"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),1*nverts*3*sizeof(GLfloat));
    glVertexAttribPointer(glGetAttribLocation(pgm,"nz"),1,GL_FLOAT,GL_FALSE,sizeof(GLfloat),2*nverts*3*sizeof(GLfloat));
    glBindBuffer(GL_ARRAY_BUFFER, color_buf);
    glVertexAttribPointer(glGetAttribLocation(pgm,"cr"),1,GL_UNSIGNED_BYTE,GL_TRUE,sizeof(GLubyte),0*nverts*4*sizeof(GLubyte));
    glVertexAttribPointer(glGetAttribLocation(pgm,"cg"),1,GL_UNSIGNED_BYTE,GL_TRUE,sizeof(GLubyte),1*nverts*4*sizeof(GLubyte));
    glVertexAttribPointer(glGetAttribLocation(pgm,"cb"),1,GL_UNSIGNED_BYTE,GL_TRUE,sizeof(GLubyte),2*nverts*4*sizeof(GLubyte));
    glVertexAttribPointer(glGetAttribLocation(pgm,"ca"),1,GL_UNSIGNED_BYTE,GL_TRUE,sizeof(GLubyte),3*nverts*4*sizeof(GLubyte));

  5. #5
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    460
    Quote Originally Posted by Pivonka View Post
    The reason is that I have got the raw data in that form and I don't want to rearrange it, as it is crazily expensive, naturally.
    Another thing. Are you doing stream or dynamic rendering ?
    If this is static, then it would certainly be better to rearrange them since you'll upload only once. Then the shaders will directly have vec3, vec4 instead of building new ones from each attribute. Your C code might also suffer less if you need to play with these values.

  6. #6
    Junior Member Newbie
    Join Date
    May 2017
    Location
    Czech Republic
    Posts
    8
    Quote Originally Posted by GClements View Post
    No. The stride will be the size of a single component ...
    Well, now I am getting a bit confused ... does this really meet my original requirement "... I need to delivery to the OpenGL engine the x-components of all vertices as a continuous series first, followed by continuous series of y-components, etc ..."? I need to feed OpenGL with continuous in-memory block of x-es (each x side-by-side with each other, nothing in between), then block of y-s, z-s and w-s ...

    Quote Originally Posted by Silence View Post
    ... If this is static, then it would certainly be better to rearrange them since you'll upload only once ...
    The process is pretty much dynamic. The raw data is coming from measuring instrument, thus varying for each rendering.

  7. #7
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    460
    Quote Originally Posted by Pivonka View Post
    Well, now I am getting a bit confused ... does this really meet my original requirement "... I need to delivery to the OpenGL engine the x-components of all vertices as a continuous series first, followed by continuous series of y-components, etc ..."? I need to feed OpenGL with continuous in-memory block of x-es (each x side-by-side with each other, nothing in between), then block of y-s, z-s and w-s ...
    Sure. You have a single buffer with all vertex x, followed by all vertex y and so on.


    Quote Originally Posted by Pivonka View Post
    The process is pretty much dynamic. The raw data is coming from measuring instrument, thus varying for each rendering.
    I understand.

  8. #8
    Junior Member Newbie
    Join Date
    May 2017
    Location
    Czech Republic
    Posts
    8
    Uhh, the stride=N (total # of vertices) is definitely nonsense, sorry for my mistake.

    But anyway, in GClements code snippet, shouldn't be rather stride=0 instead of stride=sizeof(datatype), expressing the data is "tightly packed" then?

  9. #9
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,789
    Quote Originally Posted by Pivonka View Post
    But anyway, in GClements code snippet, shouldn't be rather stride=0 instead of stride=sizeof(datatype), expressing the data is "tightly packed" then?
    Same end result; stride=sizeof(dataype) is tightly-packed in this case.

Posting Permissions

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