Vertex Attribute Buffers getting bound to wrong at

2019-08-15 06:59发布

问题:

When I bind my buffers to attributes for my shaders, they seem to be getting flipped.

So, I've got a vertex shader:

precision highp float;

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;

in vec3 in_position;
in vec3 in_color;

out vec3 ex_Color;

void main(void)
{ 
  gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
  ex_Color = in_color;
}

and a fragment shader

precision highp float;

in vec3 ex_Color;

out vec4 out_frag_color;

void main(void)
{
  out_frag_color = vec4(ex_Color, 1.0);
}

Nothing too complicated. There are two inputs: one for vertex locations, and one for colors. (As a newb, I didn't want to deal with textures or light yet.)

Now, in my client code, I put data into two arrays of vectors, positionVboData and colorVboData, and I create the VBOs...

GL.GenBuffers(1, out positionVboHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
                       new IntPtr(positionVboData.Length * Vector3.SizeInBytes),
                       positionVboData, BufferUsageHint.StaticDraw);

GL.GenBuffers(1, out colorVboHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, colorVboHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
                new IntPtr(colorVboData.Length * Vector3.SizeInBytes),
                colorVboData, BufferUsageHint.StaticDraw);

and then, I would expect the following code to work to bind the vbos to the attributes for the shaders:

    GL.EnableVertexAttribArray(0);
    GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
    GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
    GL.BindAttribLocation(shaderProgramHandle, 0, "in_position");

    GL.EnableVertexAttribArray(1);
    GL.BindBuffer(BufferTarget.ArrayBuffer, colorVboHandle);
    GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
    GL.BindAttribLocation(shaderProgramHandle, 1, "in_color");

But, in fact I have to swap positionVboHandle and colorVboHandle in the last code sample and then it works perfectly. But that seems backwards to me. What am I missing?


Update

Something weird is going on. If I change the vertex shader to this:

precision highp float;

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;

in vec3 in_position;
in vec3 in_color;

out vec3 ex_Color;

void main(void)
{
  gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
  //ex_Color = in_color;
  ex_Color = vec3(1.0, 1.0, 1.0);
}"

And make no other changes (other than the fix suggested to move the program link after all the set up, it loads the correct attribute, the vertex positions, into in_position rather than into in_color.

回答1:

GL.BindAttribLocation must be performed before GL.LinkProgram. Are you calling GL.LinkProgram after this code fragment?

EDIT: Answering to your Update - because you don't use in_color, then OpenGL simply ignores this input. And your vertex shader taks only in_position as input. Most likely it binds it in location 0. That's why your code works. You should bind locations before linking program as it is described in link above.



回答2:

So, with Mārtiņš Možeiko's help, I was able to figure this out. I was calling BindAttribLocation before LinkProgram correctly. However, I wasn't calling GL.CreateProgram() BEFORE I was binding any of the attribute locations.