Android glTexSubImage2D с проблемой GL_TEXTURE_EXTERNAL_OES (OpenGL + OpenCV + CameraX) - PullRequest
0 голосов
/ 02 февраля 2020

Я пишу приложение, использующее 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, что ожидается, как говорится в документации. Есть ли альтернативный способ скопировать буфер в GL_TEXTURE_EXTERNAL_OES после обработки OpenCV? Еще одна вещь, о которой я могу подумать, это скопировать текстуру в 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);

1 Ответ

0 голосов
/ 02 февраля 2020

Если вы заменяете все изображение и загружаете «нормальные» данные RGBA из приложения, почему это вообще должно быть GL_TEXTURE_EXTERNAL_OES типом? Просто используйте обычный GL_TEXTURE_2D.

...