2015-06-20 21 views
2

我嘗試重用Android Media Effects samples並希望能夠使用來自相機或圖庫拾取的新位圖來更改紋理數據。無解到目前爲止Android:如何更改來自圖庫/相機的OpenGLES紋理數據/位圖

這是從樣品初始加載質地:https://github.com/googlesamples/android-MediaEffects/blob/master/Application/src/main/java/com/example/android/mediaeffects/MediaEffectsFragment.java

private void loadTextures() { 
     // Generate textures 
     GLES20.glGenTextures(2, mTextures, 0); 

     // Load input bitmap 
     Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puppy); 
     mImageWidth = bitmap.getWidth(); 
     mImageHeight = bitmap.getHeight(); 
     mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); 

     // Upload to texture 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

     // Set texture parameters 
     GLToolbox.initTexParams(); 
    } 

,這是我的麻煩功能:

public void changeBackground(Uri bitmapUri) { 

    Log.d(TAG, "changeBackground : " + bitmapUri.getPath()); 

    Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath()); 
    mImageWidth = bitmap.getWidth(); 
    mImageHeight = bitmap.getHeight(); 
    mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); 

    GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap); 

    theBackground.requestRender(); //my GLSurfaceView 
    bitmap.recycle(); 
} 

我試了幾種方法:

  • 只使用texSubImage2D - >紋理未更新

  • 刪除並重新創建新的位圖紋理 - >黑色質感

注:位圖的尺寸是固定的,在1080×1080

如何改變/修改/更換新的紋理數據位圖?

UPDATE:

我認爲這個問題更涉及到這樣一個問題:Setting texture on 3D object using image from photo gallery。我從gallery意圖抓取圖像後調用changeBackground(),然後裁剪(另一個意圖)。

現在,如何有效地改變從畫廊意圖位圖紋理數據?任何人都有線索?

解決

我通過defering紋理加載過程onSurfaceChange()函數解決了這個問題。只需使用一個標誌來指示要加載的文件並onSurfaceChange再次檢查該標誌。

private Uri mFileToLoad = null; 
 

 
public void changeBackground(Uri bitmapUri) { 
 
    Log.d(TAG, "changeBackground : " + bitmapUri.getPath()); 
 
    mFileToLoad = bitmapUri; 
 
    theBackground.requestRender(); 
 
}

和我onSurfaceChange()

public void onSurfaceChanged(GL10 gl, int width, int height) { 
 
     Log.d(TAG, "onSurfaceChanged w:" + width + " h:" + height); 
 
     if (mFileToLoad!=null) { 
 
      GLES20.glDeleteTextures(mTextures.length, mTextures, 0); 
 
      GLES20.glGenTextures(mTextures.length, mTextures, 0); 
 

 
      Bitmap bitmap = BitmapFactory.decodeFile(mFileToLoad.getPath()); 
 
      mImageWidth = bitmap.getWidth(); 
 
      mImageHeight = bitmap.getHeight(); 
 
      mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); 
 

 
      // Upload to texture 
 
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]); 
 
      GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 
 

 
      // Set texture parameters 
 
      GLToolbox.initTexParams(); 
 

 
      mFileToLoad = null; 
 
      bitmap.recycle(); 
 
     } 
 

 
     if (mTexRenderer != null) { 
 
      mTexRenderer.updateViewSize(width, height); 
 
     } 
 
    }

到目前爲止,它的工作原理。

+0

你有一個以上的質感嗎?如果是這樣,你需要'glBindTexture'你想編輯的那個。 – immibis

+0

像媒體效果樣本,我有兩個紋理。一個用於原始位圖,另一個用於存儲後效應紋理。 試圖在texSubImage2D之前調用glBind,並且仍然沒有紋理更新 –

回答

1

看起來你的changeBackground()方法可能是從UI線程調用的,或者至少是除了渲染線程之外的一個線程。

GLSurfaceView創建一個單獨的渲染線程,當您的渲染方法被調用時,它具有當前的OpenGL上下文。因此它準備好您的OpenGL調用。所有其他線程都不是這種情況。當前的OpenGL上下文是,每個線程。所以除非你做了些什麼(這是可能的,但增加了很大的複雜性),你不能從其他線程進行OpenGL調用。

有幾個選項可以解決這個問題。最簡單的方法可能是在GLSurfaceView上使用queueEvent()方法,該方法允許您傳遞將在渲染線程中執行的Runnable

我不確定代碼中mTexRenderer.updateTextureSize()方法的用途。但通常,如果紋理尺寸發生變化,則必須使用GLUtils.texImage2D()而不是GLUtils.texSubImage2D()來更新紋理。

的代碼看起來是這樣的(未經測試,所以它可能不是完全一樣的類型化工作):

final Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath()); 

theBackground.queueEvent(new Runnable() { 
    @Override 
    void run() { 
     mImageWidth = bitmap.getWidth(); 
     mImageHeight = bitmap.getHeight(); 
     mTexRenderer.updateTextureSize(mImageWidth, mImageHeight); 

     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 

     bitmap.recycle(); 
    } 
}); 

theBackground.requestRender(); 
+0

是的,你是對的,但問題仍然存在。搜索後,我發現這個問題可能與圖庫有關的意圖抓住源位圖。 –

+0

您是否有透明度問題?到目前爲止,我還沒有做過很多測試,但是看起來像素像素陣列和GLES20.TexImage2D代替具有適當顏色格式的助手可以很好地顯示透明像素,而透明像素圖像加載DecodeFile然後GLUtils.TexImage2D幫助器顯示像素alpha分量爲0時的黑色像素。 –