2016-01-14 94 views
1

我正在開發基於Qt 5.4的Android系統應用程序。 我正在生成幾個OES紋理,並通過着色器在Qt FBO TEXTURE_2D中進行渲染。每個OES紋理都有自己的eglcontext,每個人都有相同的sharedContext。 OES紋理是一個接一個地使用的,我的意思是,我不想同時渲染多個紋理,但是我需要創建多個紋理,因爲我必須能夠同時渲染多個紋理未來。opengl es,glActiveTexture時出錯

這是我使用的代碼時,我必須更新:

m_program->bind(); 
glActiveTexture(GL_TEXTURE0 + textureId); 
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId); 
/* my code to fill shader attr and glDraw*() */ 
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); 
m_program->release(); 

的問題是,由於某種原因,我可以使創建的第一個OES質地,因爲我得到一個W/Adreno-ES20(28468): <core_glActiveTexture:348>: GL_INVALID_ENUM嘗試時glActiveTexture第二個。所以,目標紋理填充黑色。

我已經檢查了這一切,並是正確的:

  • textureId調用eglCreateContext時
  • sharedContext。
  • 當前eglContext呈現時,我的意思是,當調用上面的 代碼時。
  • 二OES質地已經充滿
  • GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 16
  • GL_MAX_TEXTURE_IMAGE_UNITS 16
  • GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 32

我有點失落,我不知道我這是一個限制或錯誤我的代碼。

有什麼想法?

編輯:在其他設備嘗試,應用程序正常工作,所以我認爲這個問題是關於設備的限制..

+0

既然你說第二個調用已經報告了一個錯誤,你可以嘗試硬編碼第二個GL_TEXTURE1。如果這有效,那麼你的textureId有一個奇怪的值,或者GL_TEXTURE1在你的情況下不等於GL_TEXTURE0 + 1。如果這些工作可以通過包裝紋理ID來創建解決方法,則創建另一個自定義自動增量ID,然後在包含GL_TEXTUREX枚舉的某個訪問表上使用該ID。 –

+0

@MaticOblak由於某種原因,生成的textureIds不是一個一個的,我正在檢查它的3個紋理來渲染和數字是:(oesTextureId 23)(oesTextureId 45)(oesTextureId 61) –

+0

所以這似乎是問題,然後。你可能永遠不會認爲這些ID將是連續的,或者甚至以0或任何其他低值開始。你是否仍然堅持要做什麼,或者你是否理解生成自己的自動增量活動紋理ID的概念? –

回答

2

當生成紋理你有沒有保證ID將由1.零或增量啓動,以便您可能不希望這些值爲[0,1,2,...],並且不能使用活動紋理作爲GL_TEXTURE0 + textureID。您需要創建自己的自動增量系統,通過創建一些能夠生成紋理的紋理對象,分配兩個ID等等,這是最好的。

要遞增內部ID,您只需使用一個靜態整數值,該值將爲您生成的每個紋理增加。這是最基本的系統,你只會在某些時候加載一些紋理,然後重用它們,假設它們都不應該被釋放和重用。其他系統需要包含某種對已發佈紋理的跟蹤,並且可以重新使用一個空插槽。

所以對於基礎知識,你將有一個對象/類如:

static GLint currentActiveTextureID = GL_TEXTURE0; 

class ActiveTextureObject { 
    GLuint textureID; 
    GLenum activeTextureID; 

    void generateNew() { 
     activeTextureID = currentActiveTextureID++; 
     useActive(); 
     glGenTextures(1, &activeTextureID); 
    } 

    void useActive() { 
     glActiveTexture(activeTextureID); 
    } 
    void bind() { 
     glBindTexture(GL_TEXTURE_2D, textureID); 
    } 
    void bindAndUseActive() { 
     useActive(); 
     bind(); 
    } 
}; 

這現在擁有所有你在你的代碼片段張貼的功能。如果您願意,也可以在構造函數中調用方法generateNew。正如您所看到的,該物體將紋理和活動紋理綁定在一起,因此您可以簡單地撥打bindAndUseActive來執行這兩個操作。

對於更復雜的系統,您可以使用一組代表活動紋理的插槽的元素。然後你可以遍歷數組來找到一個空插槽。

class ActiveTexturePool { 

    static const GLint maximumActiveTextures = 16; // number of maximum units 
    GLint currentActiveTextureID[maximumActiveTextures]; // have the container 

    ActiveTexturePool() { // a constructor is needed to reset the data 
     memset(currentActiveTextureID, 0, sizeof(currentActiveTextureID)); // sets all to zero 
    } 

    class ActiveTextureObject { 
    public: 
     GLuint textureID; 
     GLenum activeTextureID; 

     void generateNew() { 
      useActive(); 
      glGenTextures(1, &activeTextureID); 
     } 

     void useActive() { 
      glActiveTexture(activeTextureID); 
     } 
     void bind() { 
      glBindTexture(GL_TEXTURE_2D, textureID); 
     } 
     void bindAndUseActive() { 
      useActive(); 
      bind(); 
     } 
    }; 

    ActiveTextureObject getNewTextureObject() { 
     ActiveTextureObject toReturn; 

     for(GLint i=0; i<maximumActiveTextures; i++) { 
      if(currentActiveTextureID[i] == 0) { 
       GLenum activeTexture = GL_TEXTURE0 + i; 

       currentActiveTextureID[i] = activeTexture; 
       toReturn.activeTextureID = activeTexture; 

       return toReturn;; 
      } 
     } 
     return NULL; // the pool is full, you may not create another active texture! 
    } 

    void recycleTexture(ActiveTextureObject texture) { // remove from the pool 
     for(GLint i=0; i<maximumActiveTextures; i++) { 
      if(currentActiveTextureID[i] == texture.activeTextureID) { 
       currentActiveTextureID[i] = 0; 
       texture.activeTextureID = 0; 
       // you may also delete the data here but that should most likely be handled by the ActiveTextureObject 
       break; 
      } 
     } 
    } 
}; 

現在,在這種情況下,您寧願創建一個池來處理紋理。您可以輕鬆擁有一個或多個可用於多個上下文的池。最後,最好創建一個保存主環境並具有紋理池的類。上下文對象也可以爲您生成的每個紋理創建共享上下文,並負責刪除,回收紋理和上下文。

+0

非常感謝您的幫助,如果我告訴我在目標設備上嘗試過並且所有工作都正常,我不會開玩笑,並且我的應用能夠同時顯示至少4個(我沒有檢查更多)。我認爲這是與我的開發設備中可用的GPU內存相關的東西 –