no use of "gl_Vertex": attributes start at index 0

Hi all,

I have a vertex shader that does some vertex position computation due to some attributes. That works fine as long as “gl_Vertex” is used somewhere in the vertex shader, the attributes have indices from 1 … x. But as soon as I don’t use the “gl_Vertex” in the vertex shader, the attributes start with index 0. And index 0 is handled as vertex position -> glVertexAttrib() is handled as glVertex() :eek: -> big trouble…

Is that a known bug in GLSL?

bye,
Daniel

First, which version of Opengl, glslang are you working with?

But as soon as I don’t use the “gl_Vertex” in the vertex shader, the attributes start with index 0. And index 0 is handled as vertex position

How do you noticed this? Show us how you set up vertex buffers and vertex attributes before rendering.

I’m using Windows Vista with this driver:

Vendor: NVIDIA Corporation
Version: 2.1.2
Renderer: GeForce 8800 GT/PCI/SSE2

How can I find out the version numbers?

Source code looks like this:

int attribLocation = glGetAttribLocation(program, "attrib");
cout << attribLocation << endl;  //0 if no "gl_Vertex" in vertex shader

glBegin(GL_POINTS);
glVertexAttrib1f(attribLocation, dummy);
glVertex3fv(dummy2);
glEnd();

and vertex shader more or less like this:

attribute float attrib;

void main() {

  //gl_Position = gl_Vertex;  //this works
  gl_Position = vec4(idx1, 0.0, 0.0, 1.0);  //like this, idx1 has index 0 -->


}

Ok, this shader makes not much sense like this… anyway, if you don’t use “gl_Vertex” in your vertex shader, the attribLocation becomes 0 --> glVertexAttrib() becomes a glVertex() and two points are rendered.

Isn’t this what is expected?

In OpenGL 3.x you are not allowed to use gl_Vertex anyway I believe. You do something like this:


// binding attribute location 0 to shader variable my_own_vertex
glBindAttribLocation(program, 0, "my_own_vertex");

// setup buffers for attribute location 0
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

The vertex shader:


#version 130
in vec4 my_own_vertex;

void main(void)
{
   gl_Position = my_own_vertex;
}

So: if you are not using gl_Vertex, there is no need to bind a buffer with vertices to the shader. That means attribute location 0 (which otherwise would have been used for gl_Vertex I assume) is available. Therefore your attribute location for “attrib” is 0.

You can use something like this to check your hardware OpenGL capabilities.

Actually I am not sure to well understand your problem. An index of zero for a custom active vertex attribute is not a problem. If you are using the generic vertex attributes, you can also bind explicitely an attribute name to a particular generic attribute index calling glBindAttribLocation.

Ok, my OpenGL version is 2.1

The problem is this: if you set an attribute at index 0, then OpenGL assumes this to be actual vertex data rather than just generic attribute values.

glVertexAttrib1f(0, float_a); is the same as:
glVertex3f(flat_a, 0.0, 0.0);

But i want my attribute to be an attribute and not a vertex :wink: So the index has to be >0. glGetAttribLocation returns 0 for the first attribute if there’s no gl_Vertex in the vertex shader --> your first attribute becomes your vertex position.

if you write something like this:


int apos = glGetAttribLocation(program, "idx");
glBegin(GL_POINTS);
glVertexAttrib1f(apos, float_a);
glVertex3f(1.0, 1.0, 1.0);
glEnd();

once with shader(1):

attribute idx;

void main() {

	gl_Position = gl_ModelViewProjectionMatrix * vec4(idx, 0.0, 0.0, 1.0);

}

and once with shader(2):

attribute idx;

void main() {

	gl_Position = gl_ModelViewProjectionMatrix * vec4(idx, 0.0, 0.0, 1.0)
                      + 0.0000001 * gl_Vertex;

}

you get:
(1) two Points rendered (with strange positions because the attribute won’t work as attribute).

(2) one point with the correct position.

You have to supply either glVertex or glVertexAttrib(0, when drawing something (supplying both yields a vertex more).
These two API calls are in fact synonymous, and mark end of vertex in glBegin/glEnd block, and since glDrawArrays is specified in terms of glBegin/glEnd this propagates to all draw functions.

IOW. You can have your attribute 0 updated by glVertex or glVertexAttrib(0, doesnt matter if its consumed by generic attribute or gl_Vertex in GLSL - what matters is that you NEED to have an attribute with index 0)

Im not sure how is it in core 3.2, and other profiles that drop glBegin/glEnd, but I believe there is nothing that stops GL from drawing without any attributes at all.

This is the way I expect it to work.

When you are using OpenGL, at some point you say to the system, “I have a vertex.” You can do this either by using the attribute location 0 or by using glVertex*. These two statements are roughly equivalent. If you want to draw a vertex, you use one or the other, not both, since that triggers the creation of two vertices. This is what you found and how it is supposed to work.

It is my understading that you want to compute the vertex position based on a bunch of other attributes, not the data that you actually pass to glVertex*. Is this correct?

Here’s my example of what I think the solution is:
I want to compute the vertex position based on three attributes, a1, a2, and a3. I’m not going to use glVertex*, so a1 will be in attribute location 0. To render the vertex, I do something like this:

glBegin(...);
glVertexAttrib1f(a2_loc, a2_data);
glVertexAttrib1f(a3_loc, a3_data);
glVertexAttrib1f(a1_loc, a1_data); // this triggers the creation of a vertex
glEnd();

The shader looks something like this:


attribute float a1;
attribute float a2;
attribute float a3;
void main() {
    gl_Position = gl_ModelViewProjectionMatrix*vec4(a1, a2, a3, 1.0);
        // replace this with your actual computation of the vertex position
}

When OpenGL gets to the thrid glVertexAttrib1f command, it creates a vertex with the attributes (a1,a2,a3) == (a1_data, a2_data, a3_data). Once you are in your shader, you can do whatever you want with those values.

Theoretically, you could replace the call to glVertexAttrib1f(a1_loc, a1_data) with a glVertex1f(a1_data). In the vertex shader you could use gl_Vertex.x instead of a1.

I hope this helps…

Ok I understand your problem. In Opengl 2.1 gl_Vertex is still used and bound to the vertex attribute index 0. You can’t do anything against this.

As you said glVertexAttrib1f(0, float_a) is equivalent to glVertex3f(flat_a, 0.0, 0.0). So why calling both of them? :slight_smile:

You are setting “idx” value with “float_a” first and then you erase it with a position value. Thus idx is then equal to 1.f instead of float_a.

Simply don’t call glVertex if you don’t use any position attribute in your vertex shader. This is not a bug, several vertex attribute variables may be bound to the same index, this is call aliasing. It works as long as variables bound to the same index are not used at the same time in the vertex shader code path.

This is not a bug, several vertex attribute variables may be bound to the same index, this is call aliasing.

Actually, it is a bug. GLSL specifically disallows aliasing. NVIDIA doesn’t like this, so they generally let it happen.

To prevent unwanted aliasing, you should either use all generic attributes or no generic attributes. Don’t have a few be generic and a few not be generic.

I am not sure to understand the meaning of the italics. I just read that in the gl specs but I must admit that I never tried myself to bind more than one vertex atttribute name to one index. It is strange that the glsl spec disallow it whereas the gl spec allows aliasing. I’ll take a look to what you are refering to Alfonse.

You can use glBindAttribLocation before linking and create your attributes layout. Use same layout for all shaders, and keep attributes naming convention.