Important: Please read the Qt Code of Conduct -

Opengl textures with glDrawElements

  • I'm drawing a cube with textures, works fine when using calls to glBindTexture() and glDrawArrays() for each face.
    Can I use glDrawElements() ? If so, I'm not sure how to call glBindTexture() and how to tell wich texture should go with each face.

  • There are a number of ways to do this but glDrawElements is not a magic bullet. It is just like glDrawArrays except that you have an index buffer that tells OpenGL which order to draw the vertices in.

    Although the corners of a cube share the vertex positions they do not share normals or texture coordinates so you need to decide if using an index buffer is worth it here.

    To get a different texture on each face you could use a 2D array texture and pass in an additional vertex attribute that is an index to which texture layer to use. Then in the fragment shader you use this index to sample from the correct texture for that face.

  • Thanks for your fast replay ZapB. Since I got it working with glDrawArrays(), not sure it will be worth the trouble trying with elements. Performance should not be very different since I wil be only drawing one or two cubes.

  • Hello again. This is what I've done so far:

    @class Car
    void draw(QGLShaderProgram &m_carShader, const QMatrix4x4 &projection, QMatrix4x4 orientation);
    //car dimensions
    qreal width_lower; //largura
    qreal width_upper;
    qreal length_lower; //comprimento
    qreal length_upper;
    qreal height; //altura

    //car construction
    QVector3D car_geometry[18];
    GLint car_geometry_elements[30];
    QVector3D car_glass_geometry[8];
    QVector3D car_glass_left_lower;
    QVector3D car_glass_left_upper;
    QVector3D car_glass_right_lower;
    QVector3D car_glass_right_upper;
    QVector3D car_face_right_back_upper; //0
    QVector3D car_face_right_back_lower; //1
    QVector3D car_face_right_front_upper;//2
    QVector3D car_face_right_front_lower;//3
    QVector3D car_face_left_front_upper; //4
    QVector3D car_face_left_front_lower; //5
    QVector3D car_face_left_back_upper;  //6
    QVector3D car_face_left_back_lower;  //7

    // texture
    GLuint textures[6];
    QVector<QVector2D> texCoords;
    QList<QString> imageTexList;


    @//car dimensions
    width_lower = 0.8; //largura
    width_upper = 0.6;
    length_lower = 1.8; //comprimento
    length_upper = 1.0;
    height = 1.2; //altura

    //car construction
    car_face_right_back_lower.setX(width_lower);car_face_right_back_lower.setY(-length_lower);car_face_right_back_lower.setZ(0); //1
    car_face_right_front_upper.setX(width_upper);car_face_right_front_upper.setY(length_upper);car_face_right_front_upper.setZ(height); //2
    car_face_right_front_lower.setX(width_lower);car_face_right_front_lower.setY(length_lower); car_face_right_front_lower.setZ(0); //3
    car_face_left_front_upper.setX(-width_upper);car_face_left_front_upper.setY(length_upper);car_face_left_front_upper.setZ(height);  //4
    car_face_left_back_upper.setX(-width_upper);car_face_left_back_upper.setY(-length_lower);car_face_left_back_upper.setZ(height); //6
    car_face_left_back_lower.setX(-width_lower);car_face_left_back_lower.setY(-length_lower);car_face_left_back_lower.setZ(0); //7
    car_geometry[0] = car_face_right_back_upper;
    car_geometry[1] = car_face_right_back_lower;
    car_geometry[2] = car_face_right_front_upper;
    car_geometry[3] = car_face_right_front_lower;
    car_geometry[4] = car_face_left_front_upper;
    car_geometry[5] = car_face_left_front_lower;
    car_geometry[6] = car_face_left_back_upper;
    car_geometry[7] = car_face_left_back_lower;
    car_geometry[8] = car_face_right_back_upper;
    car_geometry[9] = car_face_right_back_lower;
    //car up
    car_geometry[10] = car_face_left_back_upper;
    car_geometry[11] = car_face_right_back_upper;
    car_geometry[12] = car_face_left_front_upper;
    car_geometry[13] = car_face_right_front_upper;
    //car bottom
    car_geometry[14] = car_face_right_back_lower;
    car_geometry[15] = car_face_left_back_lower;
    car_geometry[16] = car_face_right_front_lower;
    car_geometry[17] = car_face_left_front_lower;
    car_geometry_elements[ 0] = 0;
    car_geometry_elements[ 1] = 1;
    car_geometry_elements[ 2] = 2;
    car_geometry_elements[ 3] = 3;
    car_geometry_elements[ 4] = 4;
    car_geometry_elements[ 5] = 5;
    car_geometry_elements[ 6] = 6;
    car_geometry_elements[ 7] = 7;
    car_geometry_elements[ 8] = 0;
    car_geometry_elements[ 9] = 1;
    car_geometry_elements[10] = 0;
    car_geometry_elements[11] = 0;
    car_geometry_elements[12] = 6;
    car_geometry_elements[13] = 2;
    car_geometry_elements[14] = 4;
    // car texture images
    //car textures for: right, front, left, back, up, bottom
    for (int i=0;i<6;i++)

  • Drawing the car:

    @void Car::draw(QGLShaderProgram &m_carShader, const QMatrix4x4 &projection, QMatrix4x4 orientation)
    orientation.rotate(rotation.x(), 1.0f, 0.0f, 0.0f );
    orientation.rotate(rotation.y(), 0.0f, 1.0f, 0.0f );
    orientation.rotate(rotation.z(), 0.0f, 0.0f, 1.0f );

    QGLWidget g;
    for (int j=0; j < 6; ++j)
        textures[j] = g.bindTexture(QPixmap(, GL_TEXTURE_2D);
    GLint matrixAttr        = m_carShader.uniformLocation("matrix_shader");
    GLint projAttr          = m_carShader.uniformLocation("projection_shader");
    GLint vertexAttr        = m_carShader.attributeLocation("vertex_shader");
    GLint color             = m_carShader.uniformLocation("uColor");
    GLint textureCoordAttr  = m_carShader.attributeLocation("texCoord");

    // GLint texElementAttr = m_carShader.attributeLocation("texElements"); // ????

    m_carShader.setUniformValue( projAttr, projection );
    m_carShader.setUniformValue( matrixAttr, orientation );
    m_carShader.setAttributeArray(vertexAttr, car_geometry, 0);
    m_carShader.setAttributeArray(textureCoordAttr, texCoords.constData());
    //m_carShader.setAttributeArray(texElementAttr,textures); //error
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glDrawArrays(GL_TRIANGLE_STRIP, 2, 4);
    glBindTexture(GL_TEXTURE_2D, textures[2]);
    glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
    glBindTexture(GL_TEXTURE_2D, textures[3]);
    glDrawArrays(GL_TRIANGLE_STRIP, 6, 4);
    glBindTexture(GL_TEXTURE_2D, textures[4]);
    glDrawArrays(GL_TRIANGLE_STRIP, 10, 4);
    glBindTexture(GL_TEXTURE_2D, textures[5]);
    glDrawArrays(GL_TRIANGLE_STRIP, 14, 4);

    // glDrawElements(GL_TRIANGLE_STRIP, 15, GL_UNSIGNED_INT, car_geometry_elements);@

    The shaders:

    @attribute highp vec4 vertex_shader;
    uniform mediump mat4 matrix_shader;
    uniform mediump mat4 projection_shader;

    //variables for the car texture
    //attribute mediump vec4 texElements; // ???
    //varying mediump vec4 texElements_v; // ???
    attribute mediump vec4 texCoord;
    varying mediump vec4 texc;

    uniform mediump vec4 uColor;
    varying highp vec4 Color;

    void main(void)
    // texElements_v = texElements; //?????
    texc = texCoord; // car texture
    Color = uColor;
    gl_Position = projection_shader * matrix_shader * vertex_shader;

    @//uniform highp vec4 Color;
    varying highp vec4 Color;

    // car texture
    //varying mediump vec4 texElements_v; // ???
    varying mediump vec4 texc;
    uniform sampler2D texture;

    void main(void)
    gl_FragColor = texture2D(texture,;
    //gl_FragColor = Color;

    I tried passing the index textures to the shaders, but in line 27 from draw(), it fails because I cannot bind a GLint[] to a vec4 in the shader.

    bq. To get a different texture on each face you could use a 2D array texture and pass in an additional vertex attribute that is an index to which texture layer to use. Then in the fragment shader you use this index to sample from the correct texture for that face.

    I don't have clue how to select the texture in the fragment shader.

  • Bump on this. I am trying to accomplish a very similar task. Nor do I have a clue how to select the texture in the fragment shader. Online resources are quite disparate and I get a lot of conflicting data. Let me know if you've figured it out, or I will post my findings here

  • Still havent figured this out.
    Only thing I can think of is to use several calls to glBindTexture() and glDrawElements() in a loop, with diferent geometry elements in each call, drawing only one texture per loop, but this would not bring any benefits over glDrawArrays(). Also it would be in client side, not in the shader.

  • My thoughs exactly. I posted a similar question relegated to my project. Hopefully something will come out of it. I'm going to dig deeper into the graphics pipeline and let you know if I uncover anything

  • Here is probably the best resource on GLSL I can find:

  • You can use glDrawElements for each face

Log in to reply