ultradr3mer's picture

Vertex attribute array index

From my understanding the index is supposed to identify each Vertex attribute array, but they seem to have more influence.

This works:

                GL.EnableVertexAttribArray(1);
                GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle[i]);
                GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
                GL.BindAttribLocation(shaderHandle, 1, "in_position");
 
                GL.EnableVertexAttribArray(2);
                GL.BindBuffer(BufferTarget.ArrayBuffer, tangentVboHandle[i]);
                GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
                GL.BindAttribLocation(shaderHandle, 2, "in_tangent");

This does not:

                GL.EnableVertexAttribArray(2);
                GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle[i]);
                GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
                GL.BindAttribLocation(shaderHandle, 2, "in_position");
 
                GL.EnableVertexAttribArray(1);
                GL.BindBuffer(BufferTarget.ArrayBuffer, tangentVboHandle[i]);
                GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
                GL.BindAttribLocation(shaderHandle, 1, "in_tangent");

The not working code seems to confuse the vertex attribute arrays.
The working code works on ATI cards and multiple systems but seems to be broken for Nvidia/others (the attribute arrays seem to get mixed up).
If i dont use the "in_tangent" in the vertex Shader it also seems to confuse the attribute arrays.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mOfl's picture

Setting the array indices arbitrarily is bad practice and will lead to the behavior you are dealing with. The attribute indices correspond to the indices of incoming attributes in your shader, so either you define all indices explicitly with e.g. layout(location = 1) in vec3 in_position; which is a real pain once you share shaders for different objects, or you just leave the indexing to OpenGL and use the following instead:

int positionIndex = GL.GetAttribLocation(shaderHandle, "in_position");
int tangentIndex = GL.GetAttribLocation(shaderHandle, "in_tangent");
 
GL.EnableVertexAttribArray(positionIndex);
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle[i]);
GL.VertexAttribPointer(positionIndex, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
 
GL.EnableVertexAttribArray(tangentIndex);
GL.BindBuffer(BufferTarget.ArrayBuffer, tangentVboHandle[i]);
GL.VertexAttribPointer(tangentIndex, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);

The calls

GL.BindAttribLocation(shaderHandle, 1, "in_position");
GL.BindAttribLocation(shaderHandle, 2, "in_tangent");

only have an effect when you (re)link your shader to the shader handle afterwards, as this explicitly changes the attribute indices. Either you do this once on shader creation, or you just use GL.GetAttribLocation() as shown above.