title: Android: How to Change OpenGL ES Texture Image Dynamically
body: <p>I'm trying to change the texture image displayed on an object in my opengl view in response to a button click. Currently, when the user presses a button I set a flag to true in my OpenGL Renderer thread. My cross-thread communication seems fine: I am able to successfully toggle flag variables in the Renderer thread at will. My problem seems to be with the Open GL onDraw() workflow, I can't figure out how to systematically change a texture on an object after a texture has already been set during the Renderer's initial onSurfaceCreated() execution. </p>
  
  <p>It seems that fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood); never works outside of onSurfaceCreated(), why?</p>
  
  <p>Below is the code i've tried. Am I missing a sequence of GLES20() method invocations somewhere?</p>
  
  <p><strong>OpenGL Renderer Class</strong></p>
  
  <pre><code> private int chosenWoodColor = 1;
  
          public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
              ...
              loadFretBoardTexture();  //this call works: it succeeds in changing texture
          }
  
          public void onDrawFrame(GL10 glUnused) {
                  if (flag){    
                      loadFretBoardTexture(); //this call fails: it never changes the texture
                  }
                  ...
  
                  //***Fretboard OpenGL_TextureData Binding***
                  GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
  
                  // Bind the texture to this unit.
                  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fretBoard._textureID);
  
                  //Draw Background
                  Matrix.setIdentityM(mModelMatrix, 0);
                  Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -1.0f);
                  drawFretBoard(); //draw the fretboard
                  ...
          }
  
          public void loadFretBoardTexture(){
                  switch (chosenWoodColor){
                      case 1:
                          fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.dark_wood);
                          break;
                      case 2:
                          fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.medium_wood);
                          break;
                      case 3:
                          fretBoardTexture = new OpenGL_TextureData(mActivityContext, R.drawable.light_wood);
                          break;
                  }
                  setFretboardTextureRefresh(false);
                  return;
              }
  </code></pre>
  
  <p><strong>Texture Data Helper Class</strong></p>
  
  <pre><code>public class OpenGL_TextureData {
      public int textureID;
      public float imageWidth, imageHeight;
  
      public OpenGL_TextureData(Context context, int resourceId) { //constructor
          final int[] textureHandle = new int[1];
  
          GLES20.glGenTextures(1, textureHandle, 0);
  
          if (textureHandle[0] != 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);
  
              //fetch texture image width &amp; height
              imageWidth = options.outWidth;
              imageHeight = options.outHeight;
  
              // Bind to the texture in OpenGL
              GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
  
              // Set filtering
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
  
              // 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 (textureHandle[0] == 0) {
              throw new RuntimeException("Error loading texture.");
          }
  
          textureID = textureHandle[0];
      }
  }
  </code></pre>