我是OpenGL的新手。 我的目标是在纹理视图中处理OpenGL结构中的alpha视频。 我从视频效果开始,尝试使用自定义 [EDITED] 着色器修改一些颜色(对于开始:黑色到透明):
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES sTexture;
vec3 first;
vec4 second;
varying vec2 vTextureCoord;
vec2 oTextureCoord;
void main() {
first[0] = 0.0;
first[1] = 0.0;
first[2] = 0.0;
second[0] = 0.0;
second[1] = 1.0;
second[2] = 0.0;
second[3] = 1.0;
vec4 color = texture2D(sTexture, vTextureCoord);
oTextureCoord = vec2(vTextureCoord.x ,vTextureCoord.y + 0.5);
vec4 color2 = texture2D(sTexture, oTextureCoord);
if(vTextureCoord.y < 0.5){
gl_FragColor = vec4(color.r , color.g, color.b, color2.b);
}else{
gl_FragColor = color;
}
但我从未在视图下看过背景。 经过一些研究后我添加了
GLES20.glEnable(GLES20.GL_BLEND);
但现在“透明色”是绿色的:/
添加更多信息:源视频是上部的彩色帧和底部的alpha掩码的组合。
我做错了吗?
先谢谢。
[编辑] 这是我的实际onDrawFame方法:
@Override
public void onDrawFrame(GL10 glUnused) {
synchronized (this) {
if (updateSurface) {
mSurface.updateTexImage();
mSurface.getTransformMatrix(mSTMatrix);
updateSurface = false;
}
}
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glClearColor(1.0f,1.0f, 1.0f, 0.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT
| GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID[0]);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix,
0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glFinish();
}
- 的 [编辑] - 这是我的vertexShader:
uniform mat4 uMVPMatrix;
uniform mat4 uSTMatrix;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord
void main() {
gl_Position = uMVPMatrix * aPosition;
vTextureCoord = (uSTMatrix * aTextureCoord).xy;
}
答案 0 :(得分:1)
当我用以下颜色清除颜色时:
GLES20.glClearColor(1f, 1f, 0.9f, 0f);
[答案:如何解决]
1.首先,您需要设置GLSurfaceView以允许构造函数中的透明度:
this.getHolder().setFormat(PixelFormat.RGB_565);
this.getHolder().setFormat(PixelFormat.TRANSPARENT);
setEGLConfigChooser(8,8,8,8,16,0);
setEGLContextClientVersion(2);// all this before setRenderer()
2.请求onDrawFrame方法的透明度:
GLES20.glClearColor(0.0f, 0.0f, 0.0f, .0f);//
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT|GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
对我来说,只有黑色透明色才能使用rgba(0,0,0,0)。
再次感谢帮助我的贡献者。
- [编辑:剩余问题] -
这里有一些例子:
最重要的是,GLSurfaceView
带有一个Alpha视频,而另一个是自定义GLTextureView
,两者都在horizontalView
中。
Top似乎很好,因为我想要!但是当我向右滚动时检查这个:
当底部隐藏时,仍然会出现顶部!
答案 1 :(得分:0)
快速查看代码似乎已经有了一些奇怪的和平。我希望你至少包括你的顶点数据(位置和纹理坐标)。首先请检查
行GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT,
false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES,
mTriangleVertices);
这些看起来像纹理坐标,你有3个尺寸?那是对的吗?幸运的是,如果步幅正确,尺寸将无效,但仍然如此。
因此,如果我理解视频帧的顶部代表颜色而底部代表alpha,那么你的着色器对我来说没什么意义。你能展示顶点着色器吗?无论如何,我期望你做的是使用范围[0,1]中的纹理坐标,表示整个纹理。然后在顶点着色器中有2个不同的vec2纹理坐标,使得:
varying vec2 colorTextureCoordinates = vec2(textureCoordinates.x, textureCoordinates.y*.5); // representing the top part
varying vec2 alphaTextureCoordinates = vec2(textureCoordinates.x, textureCoordinates.y*.5 + .5); // representing the bottom part
然后在片段着色器中,您只需混合2:
vec3 color = texture2D(sTexture, colorTextureCoordinates).rgb;
float alpha = texture2D(sTexture, alphaTextureCoordinates).b; // Why .b?
gl_FragColor = vec4(color, alpha);
或者我错过了什么?为什么片段着色器中有一个IF语句,表明纹理顶部会使用颜色,底部部分会使用颜色加上alpha(或反过来)。
我建议您首先尝试使用最常见的纹理着色器绘制从视频中接收的图像,以确认正确绘制整个帧。然后你应该通过提供半透明着色器gl_FragColor = vec4(color.rgb, .5)
来检查alpha是否正常工作。确认这两个产生预期结果后,您应尝试使用colorTextureCoordinates
仅绘制框架的顶部(颜色)以获得预期结果(透明部分应为黑色)。然后使用alphaTextureCoordinates
和gl_FragColor = vec4(alpha, alpha, alpha, 1.0)
检查alpha部分,该部分应生成灰度图像,其中白色是完整的alpha而黑色不是alpha。确认所有这些之后,请按照上面的说明将它们放在一起。
要使曲面视图与其他视图混合,您需要设置透明度,并且需要使用透明颜色填充透明像素。
由于您正在使用混合,因此您需要清除背景以清除颜色(.0f, .0f, .0f, .0f)
。简单地禁用混合应该会在您的情况下产生相同的结果。
执行此操作后,您仍会看到黑色背景,因为曲面视图不会与其他视图(背景)隐式混合,只有RGB部分用于填充渲染视图。要启用透明度,您应该查看其他answers以及this one。