Thread: Vertex attributes - separated components

1. 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

2. 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. 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. Originally Posted by Pivonka
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. Originally Posted by Pivonka
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. Originally Posted by GClements
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 ...

Originally Posted by Silence
... 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. Originally Posted by Pivonka
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.

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

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. Originally Posted by Pivonka
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
•