【问题标题】:Android glTexSubImage2D with GL_TEXTURE_EXTERNAL_OES problem (OpenGL + OpenCV + CameraX)Android glTexSubImage2D 与 GL_TEXTURE_EXTERNAL_OES 问题(OpenGL + OpenCV + CameraX)
【发布时间】:2020-02-02 14:26:22
【问题描述】:

我正在编写一个应用程序,它利用 CameraX 来捕获摄像头馈送、OpenCV 来修改帧和 OpenGL 来在 GLSurfaceView 上渲染它们。

我目前的方法是从CameraX渲染原始帧,构造一个像素缓冲区,一个OpenCV Mat,使用glReadPixels将像素缓冲区(ByteBuffer)复制到Mat中,然后处理它,将像素缓冲区从Mat 写回像素缓冲区,然后使用glTexSubImage2D 将其渲染到纹理上。

问题是,CameraX 使我能够通过 GL_TEXTURE_EXTERNAL_OES 访问帧数据,根据 OpenGL 的文档,这不允许 glTexSubImage2D 修改纹理,而我目前使用下面的代码的方法不允许工作并不断抛出W/OpenGLRenderer: [SurfaceTexture-1-25873-0] bindTextureImage: clearing GL error: 0x500,正如文档所说,这是预期的。在 OpenCV 处理之后,是否有另一种方法可以将缓冲区复制到 GL_TEXTURE_EXTERNAL_OES 中?我能想到的另一件事是将纹理复制到GL_TEXTURE_2D,然后使用glTexSubImage2D,尽管我不知道该怎么做。也许有人知道另一种方法可以让我实现目标?

我的代码:

public void onDrawFrame(GL10 gl) {
    GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT );

    if(this.resolutionSet) {
        surfaceTexture.updateTexImage();

        GLES20.glUseProgram(hProgram);

        int ph = GLES20.glGetAttribLocation(hProgram, "vPosition");
        int tch = GLES20.glGetAttribLocation(hProgram, "vTexCoord");
        int th = GLES20.glGetUniformLocation(hProgram, "sTexture");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, hTex[0]);
        GLES20.glUniform1i(th, 0);

        GLES20.glVertexAttribPointer(ph, 2, GLES20.GL_FLOAT, false, 4 * 2, pVertex);
        GLES20.glVertexAttribPointer(tch, 2, GLES20.GL_FLOAT, false, 4 * 2, pTexCoord);
        GLES20.glEnableVertexAttribArray(ph);
        GLES20.glEnableVertexAttribArray(tch);

        GLES20.glReadPixels(0, 0, this.img.cols(), this.img.rows(), GL_RGBA, GL_UNSIGNED_BYTE, this.imgBuff);

        img.put(0, 0, this.imgBuff.array());

        Log.d(LOG_TAG, img.toString());

        Imgproc.cvtColor(img, img, Imgproc.COLOR_RGBA2BGRA);
        Imgproc.cvtColor(img, img, Imgproc.COLOR_BGRA2GRAY);

        this.imgBuff.clear();
        img.get(0, 0, this.imgBuff.array());

        GLES20.glTexImage2D(GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
        GLES20.glTexSubImage2D(GL_TEXTURE_EXTERNAL_OES, 0, 0, 0, img.width(), img.height(), GL_RGBA, GL_UNSIGNED_BYTE, this.imgBuff);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    }

    GLES20.glFlush();
}

以及初始化纹理的代码:

    hTex = new int[1];
    GLES20.glGenTextures ( 1, hTex, 0 );
    GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, hTex[0]);
    GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);

【问题讨论】:

    标签: android opencv opengl-es glsurfaceview android-camerax


    【解决方案1】:

    鉴于您要替换整个图像并从应用程序上传“正常”RGBA 数据,为什么这需要GL_TEXTURE_EXTERNAL_OES 类型呢?只需使用普通的GL_TEXTURE_2D

    【讨论】:

    • 这可能有效;你能告诉我,可能有一些代码,关于如何初始化新纹理,清除当前渲染的像素并将新纹理渲染到屏幕上吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多