title: OpenGL ES Android: not working textures with VBOs, working fine with the same code without VBOs
body: <p>I have a piece of code that displays a properly sized and textured rectangle (from two triangles) when I do not use VBO. When I use VBO it displays nothing on a Samsung tablet, and a proper dimensions rect but textured fully with a color taken from one of the corner pixels of the texture on HTC Evo 4G.</p>
  
  <p>I do not know what is going on since the fact it works for non VBO some sort of proves that I am setting vertexes and texture coordinates correctly, and my drawing code is also ok. I cannot find how my small piece of code enabling VBO is different from all the tutorials and articles I have found on the Internet. After spending 8 hours of my Saturday on that I decided to ask for help the people smarter than me :)</p>
  
  <p>Thanks.</p>
  
  <pre><code>public class TextureShaderProgram extends ShaderProgram {
      private final int uMatrixLocation;
      private final int uTextureUnitLocation;
      // public for performance reasons
      public final int aPositionLocation;
      public final int aTextureCoordinatesLocation;
  
      public TextureShaderProgram(Resources resources) {
          super(resources, R.raw.texture_vertex_shader, R.raw.texture_fragment_shader);
  
          uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
          uTextureUnitLocation = glGetUniformLocation(program, U_TEXTURE_UNIT);
          aPositionLocation = glGetAttribLocation(program, A_POSITION);
          aTextureCoordinatesLocation = glGetAttribLocation(program,
              A_TEXTURE_COORDINATES);
      }
  
      public void setUniforms(float[] matrix, int textureId) {
          glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
          glActiveTexture(GL_TEXTURE0);
          glBindTexture(GL_TEXTURE_2D, textureId);
          glUniform1i(uTextureUnitLocation, 0);
      }
  
  }
  
  public class VertexArray {
      private final FloatBuffer floatBuffer;
      public int vboIdx;
  
      public VertexArray(float[] vertexData) {
          floatBuffer = ByteBuffer.allocateDirect(
              vertexData.length * Constants.BYTES_PER_FLOAT).order(
              ByteOrder.nativeOrder()).asFloatBuffer().put(vertexData);
      }
  
      public void setVertexAttribPointer(int dataOffset, int attributeLocation,
              int componentCount, int stride) {
          floatBuffer.position(dataOffset);
          glVertexAttribPointer(attributeLocation, componentCount,
              GL_FLOAT, false, stride, floatBuffer);
          glEnableVertexAttribArray(attributeLocation);
          floatBuffer.position(0);
      }
  
      public void generateVBO() {
          int buffers [] = new int [1];
          glGenBuffers(1, buffers, 0);
          if (buffers[0] == 0 ) {
              throw new RuntimeException("error during VBO generation");
          }
          vboIdx = buffers[0];
      }
  
      public void loadDataToVBO() {
          floatBuffer.position(0);
          glBindBuffer(GL_ARRAY_BUFFER, vboIdx);
          glBufferData(GL_ARRAY_BUFFER, floatBuffer.capacity() * 
              Constants.BYTES_PER_FLOAT, floatBuffer, GL_STATIC_DRAW);
          glBindBuffer(GL_ARRAY_BUFFER, 0);
      }
  
      public void setVertexAttribPointerWithVBO(int dataOffset, int attributeLocation,
              int componentCount, int stride) {
          glBindBuffer(GL_ARRAY_BUFFER, vboIdx);
          glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT,
          false, stride, dataOffset);
          glEnableVertexAttribArray(attributeLocation);
          glBindBuffer(GL_ARRAY_BUFFER, 0);
      }
  
      public void clearAndPut(float [] vertexData) {
          floatBuffer.clear();
          floatBuffer.put(vertexData);
      }
  
  }
  
  public class Rect {
      public static final int VERTEXES_SIZE = 24;
      public static final int POSITION_COMPONENT_COUNT = 2;
      public static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
      public static final int STRIDE = (POSITION_COMPONENT_COUNT +         
          TEXTURE_COORDINATES_COMPONENT_COUNT) * Constants.BYTES_PER_FLOAT;
  
      private boolean reloadVBOs = true;
  
      private TextureShaderProgram textureProgram = …;
  
      private float width, height, x1, y1, x2, y2, x3, y3, x4, y4;
  
      // either VERTEXES_SIZE or VERTEXES_SIZE * number of rects in TextureAtlasRects.
      private float [] vertexes;
      /* This rect part starts at texAtlasOffset if it is a part of TextureAtlasRect.
       * If not this is just always 0 and the rest of the logc is the same
      */
      private int texAtlasOffset; 
  
      public void initVertexes(TextRectCoords texRectCoords) {
          // upper left triangle
          vertexes[0 + texAtlasOffset] = x1;
          vertexes[1 + texAtlasOffset] = y1;
          vertexes[2 + texAtlasOffset] = texRectCoords.lowerLeftTexX;
          vertexes[3 + texAtlasOffset] = texRectCoords.lowerLeftTexY;
          vertexes[4 + texAtlasOffset] = x3;
          vertexes[5 + texAtlasOffset] = y3;
          vertexes[6 + texAtlasOffset] = texRectCoords.upperRightTexX;
          vertexes[7 + texAtlasOffset] = texRectCoords.upperRightTexY;
          vertexes[8 + texAtlasOffset] = x4;
          vertexes[9 + texAtlasOffset] = y4;
          vertexes[10 + texAtlasOffset] = texRectCoords.upperLeftTexX;
          vertexes[11 + texAtlasOffset] = texRectCoords.upperLeftTexY;
          // lower right triangle
          vertexes[12 + texAtlasOffset] = x1;
          vertexes[13 + texAtlasOffset] = y1;
          vertexes[14 + texAtlasOffset] = texRectCoords.lowerLeftTexX;
          vertexes[15 + texAtlasOffset] = texRectCoords.lowerLeftTexY;
          vertexes[16 + texAtlasOffset] = x2;
          vertexes[17 + texAtlasOffset] = y2;
          vertexes[18 + texAtlasOffset] = texRectCoords.lowerRightTexX;
          vertexes[19 + texAtlasOffset] = texRectCoords.lowerRightTexY;
          vertexes[20 + texAtlasOffset] = x3;
          vertexes[21 + texAtlasOffset] = y3;
          vertexes[22 + texAtlasOffset] = texRectCoords.upperRightTexX;
          vertexes[23 + texAtlasOffset] = texRectCoords.upperRightTexY;
      }
  
      private void initVertexArray(TextRectCoords texRectCoords) {
          initAndReturnVertexes(texRectCoords);
  
          if (vertexArray != null) {
              vertexArray.clearAndPut(vertexes);
          } else {
              vertexArray = new VertexArray(vertexes);
          }
      }
  
      private void bindData(TextureShaderProgram textureProgram, boolean useVBO) {
          if (! useVBO) {
              vertexArray.setVertexAttribPointer(0, textureProgram.aPositionLocation,
                  POSITION_COMPONENT_COUNT, STRIDE);
              vertexArray.setVertexAttribPointer(POSITION_COMPONENT_COUNT,
                  textureProgram.aTextureCoordinatesLocation,
                  TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE);
              } else {
                  if (reloadVBOs) {
                      vertexArray.generateVBO();
                      vertexArray.loadDataToVBO();
                      reloadVBOs = false;
                  }
                  vertexArray.setVertexAttribPointerWithVBO(0, 
                      textureProgram.aPositionLocation, 
                      POSITION_COMPONENT_COUNT, STRIDE);
                  vertexArray.setVertexAttribPointerWithVBO(POSITION_COMPONENT_COUNT,
                      textureProgram.aTextureCoordinatesLocation, 
                      TEXTURE_COORDINATES_COMPONENT_COUNT, STRIDE);           
              }
          }
      }
  
      private void draw(TextureAndSize texture, TextRectCoords texRectCoords,
          boolean willEverChange) {
  
          textureProgram.setUniforms(projectionMatrix, texture.getTextureId());
  
          if (vertexArray == null || willEverChange) {
              initVertexArray(texRectCoords);
          }
  
          /* if the second argument below if false, then I do not use VBO and
           * everything works. If true then I use VBO and I get no rect at all
           * on Samsung Galaxy Tab S and the correct dimension rect but textured with
           * a single color, taken from one of the one pixels in the corners of the
           * texture, on HTC Evo 4G.
           */
          bindData(textureProgram, false);
  
          glDrawArrays(GL_TRIANGLES, 0, 6);
      }
  }
  </code></pre>