问题
I'm currently adding a shader system into my project and have run into a bit of a snag that I'm hoping someone can sort out. My project is written in Java, uses the LWJGL library, and targets OpenGL 2.1.
From my understanding, using the glVertexAttrib
functions set an attribute that is meant to remain constant until a new value is passed. For example, the following call should make all of my geometry white until I change it:
glVertexAttrib3f(shader.getAttributeLocation("in_Color"), 1.0f, 1.0f, 1.0f);
However, if in_Color
is bound to index 0 (which is the case when using glGetAttribLocation
), only one vertex is affected per call to glVertexAttrib3f
. For example, if I put this into my init code:
int colorLocation = shader.getAttributeLocation("in_Color");
glVertexAttrib3f(colorLocation, 1.0f, 1.0f, 1.0f);
glVertexAttrib3f(colorLocation, 1.0f, 0.0f, 0.0f);
glVertexAttrib3f(colorLocation, 0.0f, 1.0f, 0.0f);
glVertexAttrib3f(colorLocation, 0.0f, 0.0f, 1.0f);
And then attempt to render a cube using:
for(int i = 0; i < 6; i++) {
glDrawArrays(GL_TRIANGLE_STRIP, i * 4, 4);
}
This is what is rendered: http://i.imgur.com/uSuT3sH.jpg
However, if in_Color
is bound to any other attribute index, the entire cube is blue, as expected: http://imgur.com/uOVa2iA.jpg
回答1:
I've just come across this bug too.
With my Intel HD Graphics 3000, driver version 8.17.12.9632, glVertexAttrib*() works as if it's stuck between glBegin()/glEnd(). Each call presumably appends the attribute value to an internal array that is used vertex by vertex when rendering, just like with immediate mode. This array does not get cleared after flushing/swapping, so you cannot reset the values. It does look like it only happens for attribute index (location) 0.
This behavior does not match what the Nvidia card in the same machine does. You can detect Intel as the GL_VENDOR and selectively try my workaround. It appears to remind the driver that it isn't using immediate mode calls, but it only works if done in every frame that a glVertexAttrib*() call is used. Do this before your glVertexAttrib*() call once per frame:
if(apply_Intel_attrib_workaround && location == 0)
{
apply_Intel_attrib_workaround = 0;
glBegin(GL_TRIANGLES);
glEnd();
}
*apply_Intel_attrib_workaround* would have to be set to 1 after the frame is finished.
来源:https://stackoverflow.com/questions/17608643/strange-glvertexattrib-behavior