Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: glVertexAttrib() problem

  1. #1
    Advanced Member Frequent Contributor
    Join Date
    Oct 2009
    Posts
    595

    glVertexAttrib() problem

    I want to avoid the problems that will come about with OpenGL3.2 and it's dropping of glVertex().

    for this reason I do the following:

    glBegin(GL_TRIANGLES);
    glVertexAttrib3f(0, ...); // vertex coordinates
    glVertexAttrib2f(1, ...); // texture coordinates

    glVertexAttrib3f(0, ...); // vertex coordinates
    glVertexAttrib2f(1, ...); // texture coordinates

    glVertexAttrib3f(0, ...); // vertex coordinates
    glVertexAttrib2f(1, ...); // texture coordinates

    // more such calls for more triangles
    glEnd();

    The triangles appear to be rendered at correct coordinates but only the first triangle is textured correctly, all others are textured incorrectly. It looks as if t was interpolated incorrectly. What kind of mistake am I making? Here are my bare-bones shaders.

    // vertex shader
    uniform mat4 model_view_matrix;
    uniform mat4 projection_matrix;

    in vec3 in_position;
    in vec2 in_texcoords;

    varying vec2 out_texcoords;

    void main()
    {
    out_texcoords = in_texcoords;

    gl_Position = projection_matrix * model_view_matrix *
    vec4(0.5 * in_position, 1);
    }

    // fragment shader
    uniform sampler2D texture0;

    in vec2 out_texcoords;

    void main()
    {
    gl_FragColor = texture2D(texture0, out_texcoords);
    }

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,732

    Re: glVertexAttrib() problem

    You have the attributes backwards.

    Whenever you send glVertexAttrib(0), it acts like glVertex(). Which means that, in addition to sending the attribute data to attribute 0, it causes all prior attributes to combine into a single vertex (ie: causes the execution of the vertex shader).

    So if we look at your code through the eyes of OpenGL:

    Code :
    glBegin(GL_TRIANGLES);
      //First vertex
      glVertexAttrib3f(0, ...); // vertex coordinates
     
      //Second vertex
      glVertexAttrib2f(1, ...); // texture coordinates
      glVertexAttrib3f(0, ...); // vertex coordinates
     
      //Third vertex
      glVertexAttrib2f(1, ...); // texture coordinates
      glVertexAttrib3f(0, ...); // vertex coordinates
     
      //Fourth vertex
      glVertexAttrib2f(1, ...); // texture coordinates
      // more such calls for more triangles
    glEnd();

    You need to call glVertexAttrib(0) as the last data for a particular vertex.

  3. #3
    Advanced Member Frequent Contributor
    Join Date
    Oct 2009
    Posts
    595

    Re: glVertexAttrib() problem

    And of course you are perfectly right. I see it only now in the spec. Thank you.

  4. #4
    Intern Contributor
    Join Date
    Mar 2011
    Posts
    87

    Re: glVertexAttrib() problem

    i got the same question ,but i do not understand your explaination very well,can you explain that in detail?why the triangle should be drawn like that ?

  5. #5
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,732

    Re: glVertexAttrib() problem

    why the triangle should be drawn like that ?
    Short answer: Because that's how OpenGL works. There is no "why."

    Longer answer: Because OpenGL had to have some way for the user to say, "I've given you a bunch of vertex data. Now process that vertex."

    glVertexAttrib sets state. It sets the current attribute value to the given value. You can think of this state as a C/C++ struct:

    Code :
    struct VertexAttribData
    {
      vec4 attribs[16];
    };
    VertexAttribData glContextAttribs;

    Therefore, glVertexAttrib just does this:

    Code :
    void glVertexAttrib4f(attribIx, float xValue, float yValue, float zValue, float wValue)
    {
      glContextAttribs.attribs[attribIx].x = xValue;
      glContextAttribs.attribs[attribIx].y = yValue;
      glContextAttribs.attribs[attribIx].z = zValue;
      glContextAttribs.attribs[attribIx].w = wValue;
    }

    That sets state. It sets values into the struct. But OpenGL doesn't know when you've finished setting values into that struct. That is, you need a way to tell OpenGL to take the glContextAttribs and process it as a vertex.

    In the oldest days of OpenGL, there weren't numbered attributes. There were specific attributes that had a specific meaning. glTexCoord, glNormal, glVertex, etc. They still set values into a struct; you can think of them has having an implicit attribute index.

    By convention, OpenGL decided that calls to "glVertex" didn't just set data. The function(s) also told OpenGL to "use the attribute values to render stuff."

    Well, when you're working with generic attributes and GLSL, you don't use "glVertex." In order to preserve the ability to use immediate mode (glBegin()/glEnd()) rendering with GLSL and generic attributes, they had to establish a new way to tell OpenGL to "use the attribute values to render stuff."

    By convention, that new way was the setting of attribute 0 to a value. That is, any glVertexAttrib(0, ...) call would have the effect of not just setting state but also using the current attributes to render.

    They could have chosen to add a specific function for this purpose. Maybe call it "glProvokeVertex". And maybe they should have. But they didn't; they decided to use the convention of setting attribute 0. This is analogous to how vertex data worked before generic attributes, since glVertex would set state and cause rendering. But it also means that you must always have an attribute 0.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •