2014-09-02 206 views
12

我需要一种方法来渲染纹理的GL_TEXTURE_EXTERNAL_OES纹理。我尝试将纹理绑定到framebuffer,但我得到了GL_INVALID_ENUM错误。下面是一些示例代码:如何渲染到GL_TEXTURE_EXTERNAL_OES?

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); 

我的最终目标是通过在其上应用一些过滤器来修改使用表面纹理的相机框架。因此,我的着色器程序同时具有输入和输出纹理相同的GL_TEXTURE_EXTERNAL_OES纹理。这可能吗?如果没有,有没有解决方法?对于我的应用程序来说,输出纹理必须是GL_TEXTURE_EXTERNAL_OES,我不能使用GL_TEXTURE_2D纹理。

回答

0

您无法渲染到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); 

然后你包裹在SurfaceTexture对象OES质地和设置更新每个帧。你的类必须实现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纹理读取。您现在可以更改着色器程序,以任何您希望的方式渲染外部纹理数据。