我需要一种渲染为 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纹理。
答案 0 :(得分: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);
然后将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
纹理中读取。您现在可以更改着色器程序以任何方式渲染外部纹理数据。