Usage of custom and generic vertex shader attributes in OpenGL and OpenGL ES

1.1k views Asked by At

Since generic vertex attributes are deprecated in OpenGL, I tried to rewrite my vertex shader using only custom attributes. And I didn't work for me. Here is the vertex shader:

attribute vec3 aPosition;
attribute vec3 aNormal;

varying   vec4 vColor;

vec4 calculateLight(vec4 normal) {
    // ...
}

void main(void) {
    gl_Position = uProjectionMatrix * uWorldViewMatrix * vec4(aPosition, 1);
    vec4 rotatedNormal = normalize(uWorldViewMatrix * vec4(aNormal, 0));
    vColor = calculateLight(rotatedNormal);
}

This works perfectly in OpenGL ES 2.0. However, when I try to use it with OpenGL I see black screen. If I change aNormal to generic gl_Normal everything works fine aswell (note that aPosition works fine in both contexts and I don't have to use gl_Vertex).

What am I doing wrong?

I use RenderMonkey to test shaders, and I've set up stream mapping in it with appropriate attribute names (aPosition and aNormal). Maybe it has something to do with attribute indices, becouse I have all of them set to 0? Also, here's what RenderMonkey documentation says about setting custom attribute names in "Stream Mapping":

The “Attribute Name” field displays the default name that can be used in the shader editor to refer to that stream. In an OpenGL ES effect, the changed name should be used to reference the stream; however, in a DirectX or OpenGL effect, the new name has no affect in the shader editor

I wonder is this issue specific to RenderMonkey or OpenGL itself? And why aPosition still works then?

1

There are 1 answers

1
jozxyqk On BEST ANSWER

Attribute indices should be unique. It is possible to tell OpenGL to use specific indices via glBindAttribLocation before linking the program. Either way the normal way is to query the index with glGetAttribLocation. It sounds like RenderMonkey lets you choose, in which case have you tried making them separate?

I've seen fixed function rendering cross over to vertex attributes before, where glVertexPointer can wind up binding to the first attribute if its left unbound (I don't know if this is reproducible any more).

I also see some strange things when experimenting with attributes and fixed function names. Without calling glBindAttribLocation, I compile the following shader:

attribute vec4 a;
attribute vec4 b;
void main()
{
    gl_Position = gl_Vertex + vec4(gl_Normal, 0) + a + b;
}

and I get the following locations (via glGetActiveAttrib):

a: 1
b: 3
gl_Vertex: -1
gl_Normal: -1

When experimenting, it seems the use of gl_Vertex takes up index 0 and gl_Normal takes index 2 (even if its not reported). I wonder if you throw in a padding attribute between aPosition and aNormal (don't forget to use it in the output or it'll be compiled away) makes it work.

In this case it's possible the position data is simply bound to location zero last. However, the black screen with aNormal points to nothing being bound (in which case it will always be {0, 0, 0}). This is a little less consistent - if the normal was bound to the same data as the position you'd expect some colour, if not correct colour, as the normal would have the position data.

Applications are allowed to bind more than one user-defined attribute variable to the same generic vertex attribute index. This is called aliasing, and it is allowed only if just one of the aliased attributes is active in the executable program, or if no path through the shader consumes more than one attribute of a set of attributes aliased to the same location.

My feeling is then that RenderMonkey is using just glVertexPointer/glNormalPointer instead of attributes, which I would have though would bind both normal and position to either the normal or position data since you say both indices are zero.

in a DirectX or OpenGL effect, the new name has no affect in the shader editor

Maybe this means "named streams" are simply not available in the non-ES OpenGL version?

This is unrelated, but in the more recent OpenGL-GLSL versions, a #version number is needed and attributes use the keyword in.