Как сделать GL_TEXTURE_EXTERNAL_OES?

Мне нужен способ визуализации текстуры GL_TEXTURE_EXTERNAL_OES. Я попытался привязать текстуру к фреймбуферу, но получил ошибку GL_INVALID_ENUM. Вот пример кода:

glEnable(GL_TEXTURE_EXTERNAL_OES);
glGenFramebuffersOES(1, &frameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferTexture2DOES(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, outTexHandle, 0); // I get GL_INVALID_ENUM here
// set viewport, uniforms and draw 
glBindFramebufferOES(GL_FRAMEBUFFER, 0);
glDisable(GL_TEXTURE_EXTERNAL_OES);

Моя конечная цель - изменить рамку камеры с помощью SurfaceTexture, применив к ней некоторые фильтры. Поэтому моя шейдерная программа имеет как входные, так и выходные те же текстуры GL_TEXTURE_EXTERNAL_OES. Это возможно? Если нет каких-либо обходных решений? Для моего приложения важно, чтобы текстура вывода GL_TEXTURE_EXTERNAL_OES, я не могу использовать текстуру GL_TEXTURE_2D.

Ответ 1

Вы не можете отобразить текстуру GL_TEXTURE_EXTERNAL_OES. GL_TEXTURE_EXTERNAL_OES - внешняя текстура, которая отображается другими устройствами, такими как камера устройств. У вас есть доступ к этой текстуре. Если вам нужно изменить способ визуализации текстуры, вам нужно будет написать программу шейдера для этого.

Перед тем, как вы сможете получить доступ к данным текстуры OES, необходимо выполнить несколько шагов. Внешняя текстура OES должна быть инициализирована следующим образом:

int[] mTextureHandles = new int[1];
GLES20.glGenTextures(1, mTextureHandles, 0);
mTextureHandle = mTextureHandles[0];

GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureHandles[0]);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

Затем вы обертываете текстуру OES в объекте SurfaceTexture и устанавливаете его для обновления для каждого фрейма. Ваш класс должен реализовать интерфейс SurfaceTexture.OnFrameAvailableListener:

camTexture = new SurfaceTexture(mTextureHandle);
camTexture.setOnFrameAvailableListener(this);

При инициализации камеры вы должны указывать ее на использование GL_TEXTURE_EXTERNAL_OES следующим образом:

mCamera = Camera.open();
try{
    mCamera.setPreviewTexture(camTexture);
}catch(IOException ioe){
    ioe.printStackTrace();
}

Теперь в обратном вызове public void onFrameAvailable(SurfaceTexture surfaceTexture) вы переносите один из объектов GL_TEXTURE, например:

GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
camTexture.updateTexImage();
renderFrame();

В вашем методе renderFrame() вам необходимо сделать следующее:

1 - Установить окно просмотра

2 - привязка к внешней текстуре: glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId);

3 - Установите все переменные для шейдерной программы, включая матрицы преобразования

4 - Наконец, сделайте текстуру с вызовом glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Если ваша цель - изменить способ визуализации текстуры, вы должны реализовать программу шейдеров GLES для этого. Ниже приведен пример простого шейдера вершин текстуры:

uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
void main() {
    gl_Position = uMVPMatrix * aPosition;
    vTextureCoord = vec2(1.0 - aTextureCoord.s, aTextureCoord.t);
}

И вот связанный фрагмент шейдера:

#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
varying vec2 vTextureCoord;
void main(){
    gl_FragColor = texture2D(sTexture, vTextureCoord);
}

Обратите внимание, что шейдер фрагмента имеет #extension GL_OES_EGL_image_external : require в верхней части файла шейдера. Это очень важно, требуется, чтобы шейдер читал текстуру GL_TEXTURE_EXTERNAL_OES. Теперь вы можете изменить программу шейдеров, чтобы визуализировать внешние данные текстур по своему желанию.