2016-01-14 59 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内存相关的东西 –