title: Android GL How to draw different textures
body: <p>I'm in troubles with Android, GL and Textures, I have a little example and I want to load two different textures and paint it on screen, my problem is that always draws the last texture loaded. </p>
  
  <p>I'm noob with GL in android and have copied the code from some tutorials.</p>
  
  <p>Here is the code:</p>
  
  <p>GLRenderer:</p>
  
  <pre><code>public class GLRenderer implements Renderer {
  
      // Our matrices
      private final float[] mtrxProjection = new float[16];
      private final float[] mtrxView = new float[16];
      private final float[] mtrxProjectionAndView = new float[16];
  
      // Our screenresolution
      float   mScreenWidth = 1280;
      float   mScreenHeight = 768;
  
      // Misc
      Context mContext;
      long mLastTime;
      int mProgram;
  
      CardView card1;
      CardView card2;
  
      public GLRenderer(Context c)
      {
          mContext = c;
          mLastTime = System.currentTimeMillis() + 100;
      }
  
      public void onPause()
      {
          /* Do stuff to pause the renderer */
      }
  
      public void onResume()
      {
          /* Do stuff to resume the renderer */
          mLastTime = System.currentTimeMillis();
      }
  
      @Override
      public void onDrawFrame(GL10 unused) {
  
          GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
  
          // Get the current time
          long now = System.currentTimeMillis();
  
          // We should make sure we are valid and sane
          if (mLastTime &gt; now) return;
  
          // Get the amount of time the last frame took.
          long elapsed = now - mLastTime;
  
          // Update our example
  
          // Render our example
          card1.Draw(mtrxProjectionAndView);
          card2.Draw(mtrxProjectionAndView);
  
          // Save the current time to see how long it took :).
          mLastTime = now;
  
      }
  
  
      @Override
      public void onSurfaceChanged(GL10 gl, int width, int height) {
  
          // We need to know the current width and height.
          mScreenWidth = width;
          mScreenHeight = height;
  
          // Redo the Viewport, making it fullscreen.
          GLES20.glViewport(0, 0, (int)mScreenWidth, (int)mScreenHeight);
  
          // Clear our matrices
          for(int i=0;i&lt;16;i++)
          {
              mtrxProjection[i] = 0.0f;
              mtrxView[i] = 0.0f;
              mtrxProjectionAndView[i] = 0.0f;
          }
  
          // Setup our screen width and height for normal sprite translation.
          Matrix.orthoM(mtrxProjection, 0, 0f, mScreenWidth, 0.0f, mScreenHeight, 0, 50);
  
          // Set the camera position (View matrix)
          Matrix.setLookAtM(mtrxView, 0, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
  
          // Calculate the projection and view transformation
          Matrix.multiplyMM(mtrxProjectionAndView, 0, mtrxProjection, 0, mtrxView, 0);
  
      }
  
      @Override
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
  
          card1 = new CardView(mContext, 1);
          card2 = new CardView(mContext, 2);
      }
  }
  
  
  public class CardView {
  
      // Misc
      private Context mContext;
  
      // Geometric variables
      // number of coordinates per vertex in this array
      private static final int COORDS_PER_VERTEX = 3;
      private static float vertices[] = {
              10.0f, 300f, 0.0f,
              10.0f, 100f, 0.0f,
              450f, 100f, 0.0f,
              450f, 300f, 0.0f,
      };
      private static float vertices2[] = {
              450.0f, 600f, 0.0f,
              450.0f, 300f, 0.0f,
              900f, 300f, 0.0f,
              900f, 600f, 0.0f,
      };
  
      private final short indices[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
      private static float uvs[] = {
              0.0f, 0.0f,
              0.0f, 1.0f,
              1.0f, 1.0f,
              1.0f, 0.0f
      };
      private FloatBuffer vertexBuffer;
      private ShortBuffer drawListBuffer;
      private FloatBuffer uvBuffer;
  
  
      private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
  
      public CardView(Context c, int index)
      {
          // Save context reference
          mContext = c;
          // Create the triangles
          SetupCard(index);
          // Create the image information
          SetupImage(index);
  
          // Set the clear color to black
          GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1);
  
          // Create the shaders, solid color
          int vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_SolidColor);
          int fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_SolidColor);
  
          riGraphicTools.sp_SolidColor = GLES20.glCreateProgram();             // create empty OpenGL ES Program
          GLES20.glAttachShader(riGraphicTools.sp_SolidColor, vertexShader);   // add the vertex shader to program
          GLES20.glAttachShader(riGraphicTools.sp_SolidColor, fragmentShader); // add the fragment shader to program
          GLES20.glLinkProgram(riGraphicTools.sp_SolidColor);                  // creates OpenGL ES program executables
  
          // Create the shaders, images
          vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_Image);
          fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_Image);
  
          riGraphicTools.sp_Image = GLES20.glCreateProgram();             // create empty OpenGL ES Program
          GLES20.glAttachShader(riGraphicTools.sp_Image, vertexShader);   // add the vertex shader to program
          GLES20.glAttachShader(riGraphicTools.sp_Image, fragmentShader); // add the fragment shader to program
          GLES20.glLinkProgram(riGraphicTools.sp_Image);                  // creates OpenGL ES program executables
  
  
          // Set our shader programm
          GLES20.glUseProgram(riGraphicTools.sp_Image);
      }
  
  
  
      public void SetupImage(int index)
      {
          // The texture buffer
          ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4);
          bb.order(ByteOrder.nativeOrder());
          uvBuffer = bb.asFloatBuffer();
          uvBuffer.put(uvs);
          uvBuffer.position(0);
  
          // Generate Textures, if more needed, alter these numbers.
          int[] texturenames = new int[1];
          GLES20.glGenTextures(1, texturenames, 0);
  
          // Retrieve our image from resources.
          //int id = mContext.getResources().getIdentifier("drawable/test_backbground1", null, mContext.getPackageName());
          if(index == 1) {
              int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground1, index);
          }else{
              int id = riGraphicTools.loadTexture(mContext, R.drawable.test_backbground2, index);
          }
  
      }
  
  
      public void SetupCard(int index)
      {
  
          if( index == 1) {
              // The vertex buffer.
              ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
              bb.order(ByteOrder.nativeOrder());
              vertexBuffer = bb.asFloatBuffer();
              vertexBuffer.put(vertices);
              vertexBuffer.position(0);
          }else{
              // The vertex buffer.
              ByteBuffer bb = ByteBuffer.allocateDirect(vertices2.length * 4);
              bb.order(ByteOrder.nativeOrder());
              vertexBuffer = bb.asFloatBuffer();
              vertexBuffer.put(vertices2);
              vertexBuffer.position(0);
          }
  
          // initialize byte buffer for the draw list
          ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
          dlb.order(ByteOrder.nativeOrder());
          drawListBuffer = dlb.asShortBuffer();
          drawListBuffer.put(indices);
          drawListBuffer.position(0);
  
  
      }
  
      /**
       * Encapsulates the OpenGL ES instructions for drawing this shape.
       *
       * @param mvpMatrix - The Model View Project matrix in which to draw
       * this shape.
       */
  
      public void Draw(float[] mvpMatrix){
  
          // clear Screen and Depth Buffer, we have set the clear color as black.
          //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
  
          // get handle to vertex shader's vPosition member
          int mPositionHandle = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition");
  
          // Enable generic vertex attribute array
          GLES20.glEnableVertexAttribArray(mPositionHandle);
  
          // Prepare the triangle coordinate data
          GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                  GLES20.GL_FLOAT, false,
                  vertexStride, vertexBuffer);
  
          // Get handle to texture coordinates location
          int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord" );
  
          // Enable generic vertex attribute array
          GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
  
          // Prepare the texturecoordinates
          GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
                  false,
                  0, uvBuffer);
  
          // Get handle to shape's transformation matrix
          int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");
  
          // Apply the projection and view transformation
          GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);
  
          // Get handle to textures locations
          int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );
  
          // Set the sampler texture unit to 0, where we have saved the texture.
          GLES20.glUniform1i ( mSamplerLoc, 0);
  
          // Draw the triangle
          GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
                  GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
  
          // Disable vertex array
          GLES20.glDisableVertexAttribArray(mPositionHandle);
          GLES20.glDisableVertexAttribArray(mTexCoordLoc);
  
      }
  }
  
  
  public class riGraphicTools {
  
      private static final String TAG = "GraphicTools";
  
      // Program variables
      public static int sp_SolidColor;
      public static int sp_Image;
  
  
      /* SHADER Solid
       *
       * This shader is for rendering a colored primitive.
       *
       */
      public static final String vs_SolidColor =
              "uniform    mat4        uMVPMatrix;" +
                      "attribute  vec4        vPosition;" +
                      "void main() {" +
                      "  gl_Position = uMVPMatrix * vPosition;" +
                      "}";
  
      public static final String fs_SolidColor =
              "precision mediump float;" +
                      "void main() {" +
                      "  gl_FragColor = vec4(0.5,0,0,1);" +
                      "}";
  
      /* SHADER Image
       *
       * This shader is for rendering 2D images straight from a texture
       * No additional effects.
       *
       */
      public static final String vs_Image =
              "uniform mat4 uMVPMatrix;" +
                      "attribute vec4 vPosition;" +
                      "attribute vec2 a_texCoord;" +
                      "varying vec2 v_texCoord;" +
                      "void main() {" +
                      "  gl_Position = uMVPMatrix * vPosition;" +
                      "  v_texCoord = a_texCoord;" +
                      "}";
  
      public static final String fs_Image =
              "precision mediump float;" +
                      "varying vec2 v_texCoord;" +
                      "uniform sampler2D s_texture;" +
                      "void main() {" +
                      "  gl_FragColor = texture2D( s_texture, v_texCoord );" +
                      "}";
  
  
  
  
      /**
       * Utility method for compiling a OpenGL shader.
       *
       * &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When developing shaders, use the checkGlError()
       * method to debug shader coding errors.&lt;/p&gt;
       *
       * @param type - Vertex or fragment shader type.
       * @param shaderCode - String containing the shader code.
       * @return - Returns an id for the shader.
       */
      public static int loadShader(int type, String shaderCode){
  
          // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
          // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
          int shader = GLES20.glCreateShader(type);
  
          // add the source code to the shader and compile it
          GLES20.glShaderSource(shader, shaderCode);
          GLES20.glCompileShader(shader);
  
          // return the shader
          return shader;
      }
  
  
  
      /**
       * Utility method for debugging OpenGL calls. Provide the name of the call
       * just after making it:
       *
       * &lt;pre&gt;
       * mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
       * FandeckRenderer.checkGlError("glGetUniformLocation");&lt;/pre&gt;
       *
       * If the operation is not successful, the check throws an error.
       *
       * @param glOperation - Name of the OpenGL call to check.
       */
      public static void checkGlError(String glOperation) {
          int error;
          while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
              Log.e(TAG, glOperation + ": glError " + error);
              throw new RuntimeException(glOperation + ": glError " + error);
          }
      }
  
      public static int loadTexture(final Context context, final int resourceId, int[] textureHandler, int index)
      {
  
          //GLES20.glGenTextures(1, textureHandler, index);
  
          if (textureHandler[index] != 0)
          {
              final BitmapFactory.Options options = new BitmapFactory.Options();
              options.inScaled = false;   // No pre-scaling
  
              // Read in the resource
              final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
  
              // Bind to the texture in OpenGL
              GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandler[index]);
  
              // Set filtering
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
  
              // Load the bitmap into the bound texture.
              GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
  
              // Recycle the bitmap, since its data has been loaded into OpenGL.
              bitmap.recycle();
          }
  
          if (textureHandler[index] == 0)
          {
              throw new RuntimeException("Error loading texture.");
          }
  
          return textureHandler[0];
      }
  }
  </code></pre>