PDA

View Full Version : GLSL design & glVertexAttribPointer question.



Red_Riot
03-09-2011, 09:04 PM
Doing really well on an OpenGL 3.1 shader supported wrapper, but before I go any further I have some questions about the OpenGL 3.1+ and GLSL #version 150 design. I'm familiar with the current (and outdated) GLSL Red Book and Orange Book.

Question #1: Assumption: As far as getting information to and from GLSL via 'in' variables using glDrawElements, glDrawArrays ect and the like, we have only the glVertexAttribPointer
Is this true?
(rephrase: the only way to set variables when the draw functions are called are to set varriable ids to be linked by glVertexAttribPointer)

Question #2: Assumpion: glVertexAttribPointer is ONLY able to retrieve data from the VBO, or Vertex Buffer Objects set by glBufferData(GL_ARRAY_BUFFER, sizeof(your_data), your_data, DRAW_MODE). There is no way to make it draw from other arrays like the GL_ELEMENT_ARRAY or some generic data buffer?
True or false?
(rephrase: when using glDrawElements ect, the variables automatically set by their glVertexAttribPointer bindings can ONLY draw from the GL_ARRAY_BUFFER);

IS THE FOLLOWING TRUE:
If i wish to obtain and update in variables in my GLSL shader programs when using draw calls like glDrawElements, all of the information I wish to obtain must be packed in the GL_ARRAY_BUFFER.


My situation:
Here's the situation, My shaders all work with my new drawing system, however I'm looking to draw from an index (GL_ELEMENT_ARRAY_BUFFER) to a vertex buffer. It needs to pass info from the vertex specified by the index, and the texture coords of that vertex. (there's more but coords are all I need for the example)
Because the above is true, I need to pack texture coord data, and anything else I want updated and passed into the GL_ARRAY_BUFFER via some sort of interleaved array correct?


Thanks for the help, I need to understand this limitation before I design an array to hold the data I need.

Red_Riot
03-09-2011, 09:21 PM
As an amendment, here's the hurdle I'd like to overcome:

Using an indexed method I only have to define a vertex once, and then I can index it however many times I want. However, i'd like to be able to store the index to the vertex, along with texture coords ect data for that index reference and pass that to my vertex shader.

With the current setup, I'm locked into needing a redundant declaration of the vertex because I'm forced to store the data in the GL_ARRAY_BUFFER.

the attribute pointers read from a const offset for x ammount of data.

I'd like to reference data like this:
vertexdata = {lots of vertex data};
data = {index_to_vertex, coorddata, coorddata}

with the limitation I can't use an index and have to store EACH vertex as
data = {x, y, z, coorddata, coorddata}; which is a waste.

Alfonse Reinheart
03-09-2011, 09:23 PM
Question #1: Assumption: As far as getting information to and from GLSL via 'in' variables using glDrawElements, glDrawArrays ect and the like, we have only the glVertexAttribPointer

Well, there's also glVertexAttribIPointer for integral vertex attributes.


Question #2: Assumpion: glVertexAttribPointer is ONLY able to retrieve data from the VBO, or Vertex Buffer Objects set by glBufferData(GL_ARRAY_BUFFER, sizeof(your_data), your_data, DRAW_MODE). There is no way to make it draw from other arrays like the GL_ELEMENT_ARRAY or some generic data buffer?

Yes and no. As stated here (http://www.opengl.org/wiki/Vertex_Specification), the only thing that matters is the particular buffer object bound to GL_ARRAY_BUFFER at the time you call glVertexAttribPointer. Any changes you make after this, unless they involve calling glVertexAttribPointer for that same attribute again, don't matter.

For example, if you do this:



glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glDraw...;


The data for vertex attribute 0 will come from "buffer1", not "buffer2". That's because "buffer1" was the active buffer when glVertexAttribPointer was called.

So if you want to pull attribute 0 from "buffer1" and attribute 1 from "buffer2", then you do this:



glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(1, ...);
glDraw...;



Here's the situation, My shaders all work with my new drawing system, however I'm looking to draw from an index (GL_ELEMENT_ARRAY_BUFFER) to a vertex buffer.

What does that mean? There's no such things as an index buffer or a vertex buffer. There are only buffer objects, which can be used as sources for index data or vertex attribute data (among other things). If you want to bind a buffer to GL_ELEMENT_ARRAY_BUFFER for one rendering command, and bind it to GL_ARRAY_BUFFER for another, that's fine. If you want to bind it to both for the same rendering command, that's also fine.

Red_Riot
03-09-2011, 09:26 PM
Thanks for your reply Alfonse, i'll try to clarify in a bit but I need to head to work right now, read the amendment above if you would.

I'll post a more well developed explanation when I get on break.


The updating of 'in' variables needs to be completed ENTIRELY within the call of 'glDrawElements'

so it needs to : load 3 in_vertex data floats
load 2 texture coords

for however many vertex are in the data set.

Both of these values have no choice but to be taken from the currently bound GL_ARRAY_BUFFER.

Dan Bartlett
03-10-2011, 04:05 AM
Both of these values have no choice but to be taken from the currently bound GL_ARRAY_BUFFER.

No. As Alfonse said, you don't need to have a buffer object bound to the GL_ARRAY_BUFFER binding point at all when you make the draw call. The association between an attribute + the buffer object the data comes from is made at the point of the glVertexAttribPointer call. OpenGL stores the buffer object bound to GL_ARRAY_BUFFER at that point. Therefore, you can have multiple attributes coming from different buffer objects.

You could call glBindBuffer(GL_ARRAY_BUFFER, 0); before the draw call + it will have no impact, but it makes it clearer that it isn't used at all.

Reading your earlier posts a bit more, are you looking for the gl_VertexID variable?

Red_Riot
03-10-2011, 03:15 PM
That makes sense, I was under the assumption that the glVertexAttribPointer call set a blanket pointer for whatever the currently enabled GL_ARRAY_BUFFER was, and didn't realize it was a set binding to a memory address of the enabled buffer at bind time.

And disregard my earlier posts, that was during an upgrade to GLSL #version 150 shaders and there was a bit of confusion. My shaders all work appropriately, translate and draw themselves nicely with the new OpenGL 3.1+ and GLSL 150.

In regards to the topic, I was looking to make a call to GlElements (or some permutation of the draw functions) that would do the following for n elements:
vertex data = {xn,yn,zn,...}
coord data = {sn, tn,...}

and take an index, such as {vertN, coordN,...}
and index vertex and data arrays loading via my Attrib pointers into GLSL
vec3 xn, yn, zn
vec2 sn, st
all with a single draw call that would plow through the array.

If I want to do this, I can't have an indexed array. well I can, but each index would be redundant since I can't dictate two different indexes, so I'd have to redefine each vertex and coord data set anyways.

SO this leaves me with the only option of a straight up non indexed array of for n elements.
{xn, yn, zn, sn, sn,...}

Thanks for the help by the way.

Alfonse Reinheart
03-10-2011, 03:25 PM
and take an index, such as {vertN, coordN,...}

You only get one index. Each index is applied to all active attribute arrays.


SO this leaves me with the only option of a straight up non indexed array of for n elements.

No, it doesn't. You just have to ensure that each index represents a unique grouping of position and texture coordinate.

For example, if your input index list, the one that indexes from positions and texcoords separately is this:

{0, 0}
{1, 1}
{2, 2}
{1, 1}
{3, 3}
{2, 4}

This can generate an OpenGL index list like so:

{0}
{1}
{2}
{1}
{3}
{4}

The second and fourth indices are the same, because all of the original indices are the same. The last index is new, because it represents a previously unused combination of position and texture coordinate.

Red_Riot
03-10-2011, 03:46 PM
Yeah good example, that's what I figured from the design limitations. More than enough info to design an appropriate array format, thank you for your help on clarifying the bindings.