我想用一些质地叠加混合相机预览表面纹理。 我使用这些着色器处理:
private final String vss = "attribute vec2 vPosition;\n"
+ "attribute vec2 vTexCoord;\n"
+ "varying vec2 texCoord;\n"
+ "void main() {\n"
+ " texCoord = vTexCoord;\n"
+ " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n"
+ "}";
private final String fss = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "uniform sampler2D filterTexture;\n"
+ "varying vec2 texCoord;\n"
+ "void main() {\n"
+" vec4 t_camera = texture2D(sTexture,texCoord);\n"
//+" vec4 t_overlayer = texture2D(filterTexture, texCoord);\n"
//+ " gl_FragColor = t_overlayer;\n" + "}";
+ " gl_FragColor = t_camera;\n" + "}";
我的目标是混合t_camera和t_overlayer。 当我分开显示t_camera或t_overlayer,它的工作原理(表示相机预览或纹理)。 但是,当我取消t_overlayer,然后t_camera变成黑色(严重莫名其妙采样)。 我的覆盖层的质地是512×512和CLAMPT_TO_EDGE。 Android模拟器,HTC EVO 3D:例如只出现此问题。 但在SGS3,HTC One X的,它工作得很好。
怎么了? 难道EVO 3D缺少一些扩展还是什么?
Answer 1:
我想你有这样的问题,因为你不设置您的代码正确的纹理ID。 这是在其似乎是合乎逻辑的假设一个tipical错误,但实际上不是文档定义如此。 如果选中该扩展你看到下面的(编辑)的文本文档:
每个TEXTURE_EXTERNAL_OES纹理对象可能需要与它结合的每个纹理单元最多3纹理图像单元。 当被设定为TEXTURE_EXTERNAL_OES 这个值将是1和3(包含在内) 之间 。 对于其他有效的纹理目标这个值将总是1。注意的是,当一个纹理TEXTURE_EXTERNAL_OES对象绑定, 由单个纹理单元可以是1,2或3,而对于其他纹理对象每个所需的纹理图像单元的数量纹理单元需要正好1纹理图像单元。
这意味着,在执法机关一个额外的将工作,只要您使用ID 0它。 你的情况:
GLES20.glUniform1i(sTextureHandle, 1);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
sTextureId);
为了您的2D纹理:
GLES20.glUniform1i(filterTextureHandle, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterTextureID);
我敢肯定,你这样会锻炼。
Answer 2:
我得到了我的Nexus 7相同的问题,它让我抓狂。 访问无论是samplerExternalOES或sampler2D工作完全正常,但在相同的着色器访问他们俩给了意想不到的效果。 有时,输出会是黑色的。 有时查找之一的输出将有不好的量化伪像。 该行为也将根据不同的纹理单元在哪里绑定到采样变化。 我做了检查每一个OpenGL的错误和validateProgram结果。
最终,什么工作是使用一个单独的着色器简单地访问摄像机的输出和渲染到纹理。 然后将得到的质地可以通过定期sampler2D访问和一切工作完全按照预期。 我怀疑有地方有关samplerExternalOES的错误。
Answer 3:
上述方法节省大量的我的时间。 谢谢大师:
GLES20.glUniform1i(sTextureHandle, 1);
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
sTextureId);
为了您的2D纹理:
GLES20.glUniform1i(filterTextureHandle, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterTextureID);
改变纹理指数是解决这个的好办法。
Answer 4:
这似乎是在OpenGL实现的一个错误。 相同的代码工作正常三星注,而不是在Nexus 4看起来getUniformLocation上对位于过去samplerExternalOES所有变量的一些设备打破。
这也似乎是编译器alphabeticaly统一排序变量,这样使得它在两个设备上工作的解决办法是重新命名您的samplerExternalEoz是zzzTexture什么的。
Answer 5:
这不是一个答案,而是问题的阐述 - 也许这会帮助一个OpenGL ES专家,得到这个问题的想法。
我已经使用了叠加3个纹理和一个外部的纹理,用于捕获从媒体播放器的输出。 如果我只用外部的质感,输出为预期,从MPlayer的框架。 相同的全代码工作正常上Nexus4,三星Galaxy S3,S4等(所有设备使用肾上腺的GPU,或臂的的Mali400)在硬件的区别在于的Nexus 7使用的NVIDIA Tegra 3板。
编辑 (如何解决了在我身边):
Nvidia的Tegra 3的要求,外部纹理采样器被称为与采样中最低的字母顺序的名称,同时为Adreno 220,似乎需要反向。 另外,T3需要外部纹理一次取样。 随着采用Android 4.3和较新的设备,这些缺陷可能会得到解决。 在NVIDIA方面,这是一个错误,早就解决了,但司机的Nexus只以后更新。 所以我不得不来检查哪些GPU的存在,并相应地调整代码。
Answer 6:
参照user1924406的帖子( https://stackoverflow.com/a/14050597/3250829上分裂访问sampler2D质地和纹理samplerExternalOES),这是我必须做的,因为我正在开发的应用程序从一个文件中读取或从服务器流式传输,而不是使用摄像头,在设备上。 在相同的着色器同时使用纹理造成非常怪异colourization工件(在银河S3的情况下)或饱和度和对比度的问题(在Nexus 4的情况下)。
因此,唯一的办法来解决samplerExternalOES质感的bug(从我迄今所看到的)是做两个着色器程序:一个是写入包含在samplerExternalOES质感的FBO的内容和采取其他从FBO内容和直接写入其在表面上。
你需要检查的一件事是,有时,当你写一个FBO,纹理坐标翻转。 在我的情况下,V(或T或Y)坐标被翻转其导致跨越水平轴的镜像图像。 我曾在第二阶段写片段着色器时要考虑到这一点。
这是一场战争的故事,我想分享的情况下有一些你可能需要从文件或流从服务器读取直接从相机拍摄来代替。
Answer 7:
我可能有同样的问题也是如此。 试图天后,我在这里提出我的解决方案。 希望这会帮助别人。
首先,问题的陈述。 就像卢卡斯Jezný,我有一个预览质地和一个覆盖质感。 它工作正常关系和4/5大多数其他类型的,但说明不了什么对OPPO找到5,联想A820,联想A720。
解:
(1)就像卢卡斯Jezný,使用YUV数据,并在着色它们转换为RGB。
(2)多道图纸,绘制预览纹理帧缓冲一次,读它,然后再绘制到屏幕上。
(3)您使用自己的程序之前使用其它程序,
GLES20.glUseProgram(another one);
GLES20.glUseProgram(your "real" program);
它只是适用于OPPO找到5,联想A820,联想A720等。 没有人知道为什么......
Answer 8:
为了外部的纹理(非GPU)转换为定期的内部一个,你必须
- 首先创建一个外部的纹理(同创建常规的质感,但替换所有
GLES20.GL_TEXTURE_2D
与GLES11Ext.GL_TEXTURE_EXTERNAL_OES
)。 - 创建一个内部/规则纹理写入
- 紧裹
SurfaceTexture
与外部质感。 - 读(从照相机,文件等如果)的含量成外部纹理
- 覆盖
onFrameAvailable
是表面纹理的,在这里做转换,既提供外部纹理从阅读,内部质地写。 - 您可能需要调用
getTransformMatrix
在坐标校正(通常翻转Y轴),并提供它。 有时候不...
这里的一些例子着色器:
顶点shdaer -
uniform mat4 transform; // might be needed, and might not
uniform mat4 modelview;
uniform mat4 projection;
attribute vec2 position;
varying vec2 vTexcoord;
void main() {
gl_Position = projection * modelview * vec4(position.xy, 0.0, 1.0);
// texture takes points in [0,1], while position is [-1,1];
vec4 newpos = (gl_Position + 1.0) * 0.5;
vTexcoord = (transform * newpos).xy ;
}
片段着色器 -
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
varying vec2 vTexcoord;
void main() {
gl_FragColor = texture2D(sTexture, vTexcoord);
}
文章来源: Android OpenGL combination of SurfaceTexture (external image) and ordinary texture