PDA

View Full Version : Garbage triangles if I access gl_MultiTexCoord0



doug65536
10-26-2011, 12:09 AM
I'm converting everything over to use shaders and I'm blocked by what appears to be a driver bug.

If I read gl_MultiTexCoord0 in my shader, instead of getting proper polygons, I get garbage random vertices only on the geometry that has textures.

Removing the read of gl_MultiTexCoord0 fixes the random vertices.

I have a very simple shader generator right now. Here are the shaders:

Vertex shader:

attribute mat4 mat;
attribute mat4 matproj;
varying vec3 lightnormal;
varying vec4 vertpos;
varying vec2 textureCoord;
void main()
{
mat3 normalmatrix = mat3(vec3(mat[0]),vec3(mat[1]),vec3(mat[2]));
lightnormal = normalmatrix * gl_Normal;
vertpos = mat * gl_Vertex;
textureCoord = gl_MultiTexCoord0;
gl_Position = matproj * gl_Vertex;
}



fragment shader:

varying vec2 textureCoord;
uniform sampler2D textureMap;
varying vec3 lightnormal;
varying vec4 vertpos;
void main(){vec3 lightnorm = normalize(lightnormal);
gl_FragColor = vec4(textureCoord.s, textureCoord.t, 0, 1) * (0.5 + 1.0);
}


They're "debug" shaders, they simply use the vertex coordinate as the color.

Is there a reason it would "go crazy" if I access gl_MultiTexCoord0?

I'm using a VAO + vbo for vertices + glInterleavedArrays(GL_T2F_N3F_V3F, ...) + vbo element buffer + glvertexattribpointer for the mat and matproj (for instancing).

Windows 7 ultimate 64-bit, nvidia version 285 drivers (did same on previous version, 280).

If I try to use VertexAttribPointer for the texture coord (using "attribute vec2 tc"), it stops "going crazy" with garbage triangles, and geometry randomly disappears/appears based on camera location, and I don't get any proper texture coordinates.

I am using GL_debug_output and I don't have any errors happening (I get lots of verbose info about some buffers being in system memory / video memory / etc)

I've wasted a ridiculous amount of time on what really seems like a driver bug. I am experienced enough to resist that thought and to try to believe that the problem actually is my fault =).

Any help or insights would be GREATLY appreciated!

Thanks.

Alfonse Reinheart
10-26-2011, 12:15 AM
I'm using a VAO + vbo for vertices + glInterleavedArrays(GL_T2F_N3F_V3F, ...) + vbo element buffer + glvertexattribpointer for the mat and matproj (for instancing).

Is that even legal?

You generally should never use interleaved arrays. You don't need them; just set up your interleaving with glVertexAttribPointer or other glVertex*Pointer.

Also, you are using a lot of attributes. One nice thing about using user-defined attributes is that you know exactly how many you're using. So you may want to check to see if you aren't using them all up.

doug65536
10-26-2011, 12:27 AM
http://postimage.org/image/n2dccel27/

doug65536
10-26-2011, 12:36 AM
It isn't legal? I assumed that glInterleavedArrays was a wrapper around gl*Pointer calls.

I tried taking out the glInterleavedArrays and using gl*Pointer calls. It didn't fix anything. I'll try using ALL custom attributes.

You're saying bypass all the nice elegant and easy to use gl_Vertex (etc) builtins and do it ALL using custom vertex attributes?

Alfonse Reinheart
10-26-2011, 12:50 AM
It isn't legal? I assumed that glInterleavedArrays was a wrapper around gl*Pointer calls.

According to GL 4.2, it is. But that doesn't mean it's a good idea.


You're saying bypass all the nice elegant and easy to use gl_Vertex (etc) builtins and do it ALL using custom vertex attributes?

I don't see anything nice, elegant, or easy about those. They don't behave like other attributes, but they take up resources all the same. They don't look like other attributes; they are undeclared variables that seemingly come out of nowhere.

It's a lot more confusing to someone who hasn't seen a shader if they see a lot of random `gl_Vertex` use, particularly when it isn't explicitly defined.

Also, NVIDIA has had more than a few driver bugs around aliasing between user-defined attributes and built-in ones.

doug65536
10-26-2011, 01:41 AM
Ok, I guess I'm having some trouble letting go of "old" OpenGL.

What feels inelegant (I guess) is having to setup the vertexattribpointer(s) repeatedly, for each different shader that uses the same geometry.

My issue is a problem with the built-ins so it's good to get confirmation that it probably is a driver bug. At least I can stop looking for a bug in my code that probably isn't there.

I'm changing it over to use all explicitly defined attributes (and no built-ins), and using glVertexAttribPointer for everything, and no gl*Pointer calls.

doug65536
10-26-2011, 05:00 AM
Alfonse, you are awesome! Switching everything over to explicit attributes ended up solving my issue.

I am concerned that I am still not doing something quite right:

When I'm making my EnableVertexArray and glVertexAttribPointer calls, I'm using the value returned by GetAttribLocation. I read some confusing information on this and other sites, showing people using 0, 1, 2, etc as the parameter to EnableVertexArray. I also understand that there may be a limit of 16 attributes. In my code, the first "attribute location" is 10. Is it correct to use EnableVertexArray(10) then? Or should I be doing something with BindVertexLocation? I'm confused.

Thanks!

Dan Bartlett
10-26-2011, 05:40 AM
I guess this is still relevant:

http://developer.download.nvidia.com/opengl/glsl/glsl_release_notes.pdf

It lists the aliased attributes as:


Built-in vertex attribute name / Incompatible aliased vertex attribute index
gl_Vertex 0
gl_Normal 2
gl_Color 3
gl_SecondaryColor 4
gl_FogCoord 5
gl_MultiTexCoord0 8
gl_MultiTexCoord1 9
gl_MultiTexCoord2 10
gl_MultiTexCoord3 11
gl_MultiTexCoord4 12
gl_MultiTexCoord5 13
gl_MultiTexCoord6 14
gl_MultiTexCoord7 15

You can either use glGetAttribLocation to query attribute locations, in which case the driver will auto allocate to slots that aren't being used by pre-defined attributes, or alternatively you can set them yourself using glBindAttribLocation. If you use glBindAttribLocation, you will need to make sure you don't use a value that is already in use by one of the predefined attributes. Eg. don't use attribute 0 if you're using gl_Vertex, or attribute 8 if you're using gl_MultiTexCoord0.

Dan Bartlett
10-26-2011, 06:22 AM
One way you can get round lots of glVertexAttribPointer calls is by having multiple stored objects in one buffer object and call glVertexAttribPointer pointing to the start of the buffer. Then you need to change the last argument to glDrawElements to draw each object. You only need to make the glVertexAttribPointer calls when you switch buffer objects.

You'll need to adjust the indices of the objects as you store the vertices in the buffer object, unless you use the GL_ARB_draw_elements_base_vertex (http://www.opengl.org/registry/specs/ARB/draw_elements_base_vertex.txt) extension.

Without GL_ARB_draw_elements_base_vertex, if you were to insert an object with 300 vertices into the buffer object, the vertices would be indexed as 0, 1, 2 .. 298, 299. If you were to insert another object with 3 vertices into the same buffer object, they would need to be indexed as 300, 301 and 302.

With GL_ARB_draw_elements_base_vertex, you can copy all the indices to the buffer object without adjusting them. So object 1 would have vertices with indices 0 to 299 and a base vertex of 0. Object 2 would also have vertices with indices 0, 1 and 2, but a base vertex of 300.

To draw them, you would then call:


glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0, 0);
glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0, 300);

Alfonse Reinheart
10-26-2011, 10:09 AM
I read some confusing information on this and other sites, showing people using 0, 1, 2, etc as the parameter to EnableVertexArray. I also understand that there may be a limit of 16 attributes. In my code, the first "attribute location" is 10. Is it correct to use EnableVertexArray(10) then? Or should I be doing something with BindVertexLocation? I'm confused.

In general, most people explicitly define attribute locations for their attributes, either with glBindAttribLocation before linking the program or with GL 3.3/ARB_explicit_attrib_location. By doing this, each program can use a consistent sequence of attributes. The position is always `0`, the color is always `1`, etc. So you can render the same mesh with different shaders without changing attributes at all.

Or if multiple meshes have the same vertex format, you can do what Dan suggests.