Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are there multiple ways to pass VAOs to a GLSL program?

Tags:

opengl

glsl

Sample code:

1. glGenBuffers(1, &VboId);
2. glBindBuffer(GL_ARRAY_BUFFER, VboId);
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
5. glEnableVertexAttribArray(0);

So the "0" on lines 4 (first argument) and 5 refer to an arbitrary identifier/location that we have chosen. In GLSL, if we want to refer to this data, we just have to refer to the same ID:

layout(location=0) in vec4 in_Position;

However, in a different example program, I've seen it done differently, with no reference to "layout locations". Instead, we do something like so:

1. glGenBuffers(1, &VboId);
2. glBindBuffer(GL_ARRAY_BUFFER, VboId);
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
5. glBindAttribLocation(shaderProgramHandle, 0, "in_position");
6. glEnableVertexAttribArray(0);

We've added an extra step (5) where we seem to bind this attribute pointer to a specific variable in a specific program. And then in our GLSL we just write this instead:

in vec3 in_position;

With no reference to a location.

If I'm not mistaken, these 2 programs essentially do the exact same thing...so why the difference? What are the pros and cons of each method?

(I've just started learning OpenGL 3.x)

like image 211
mpen Avatar asked Jan 01 '12 03:01

mpen


1 Answers

There is no such thing as passing a VAO to a shader. A VAO simply establishes how vertex attributes are pulled from buffer objects for rendering.

The second example doesn't do anything, unless shaderProgramHandle has not been linked yet. glBindAttribLocation location only works before program linking. Once the program has been linked, you can't change where it gets its attributes from.

In any case, your real question is why some people use glBindAttribLocation(..., 0) instead of putting layout(location = X) in their shaders. The reason is very simple: layout(location) syntax is (relatively) new. glBindAttribLocation dates back to the very first version of GLSL's OpenGL interface, back in the ARB_vertex_shader extension back in 2003 or so. layout(location) comes from the much more recent ARB_explicit_attrib_location, which is only core in GL 3.3 and above. 3.3 only came out in 2010. So naturally more material will talk about the old way.

The "pros and cons" of each are quite obvious. From a purely practical standpoint, layout(location), being new, requires more recent drivers (though it does not require GL 3.3. NVIDIA's 6xxx+ hardware supports ARB_explicit_attrib_location despite being only 2.1). glBindAttribLocation works within source code, while layout(location) is built into the GLSL shader itself. So if you need to decide which attributes use which indices at runtime, it's a lot harder to do it with layout(location) than without it. But if, like most people, you want to control them from the shader, then layout(location) is what you need.

like image 62
Nicol Bolas Avatar answered Sep 18 '22 09:09

Nicol Bolas