我正在Android系统中开发基于Qt 5.4的应用程序。
我正在生成多个OES纹理,并通过着色器在Qt FBO TEXTURE_2D中进行渲染。每个OES纹理都有自己的eglcontext,每个人都有相同的sharedContext。 OES纹理是一个接一个地使用的,我的意思是,我不想同时渲染多个纹理,但由于我必须能够同时渲染多个纹理,因此我需要创建多个纹理。未来。

这是我必须更新时使用的代码:

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纹理,因为尝试第二个glActiveTexture时得到一个W/Adreno-ES20(28468): <core_glActiveTexture:348>: GL_INVALID_ENUM。因此,目标纹理填充为黑色。

我已经检查了所有这些并且是正确的:


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


我有点迷茫,我不确定这是代码中的限制还是错误。

有什么想法吗?

编辑:在其他设备上尝试,应用程序正常工作,所以我认为问题与设备限制有关。

最佳答案

生成纹理时,您无法保证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;
            }
        }
    }
};


现在,在这种情况下,您宁愿在某个地方创建一个池来处理纹理。您可能很容易拥有一个或多个池,这些池对于多个上下文很有用。最后,最好创建一个包含主上下文并具有纹理池的类。然后,上下文对象还可以为要生成的每个纹理创建共享上下文,并且还负责删除,回收纹理和上下文。

关于android - opengl es,glActiveTexture时出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34798281/

10-12 05:21