【问题标题】:Android GL_BLEND no alpha and GREEN BackgroundAndroid GL_BLEND 没有 alpha 和绿色背景
【发布时间】:2016-01-11 17:32:15
【问题描述】:

我是 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();

    }

--[编辑]-- 这是我的顶点着色器:

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

【问题讨论】:

  • 你用什么做背景色?如果背景是黑色的,我希望“透明”颜色是淡黄色的。
  • 如果你的意思是 VideoSurfaceView 的背景颜色来自 videoeffect 我没有设置背景,也没有人到下面的视图。
  • 是的@RetoKoradi 我的“透明”颜色呈黄色和绿色。
  • 将着色器修改为当前着色器和 onDrawFrame 方法!

标签: android opengl-es


【解决方案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)。

再次感谢帮助我的贡献者。

--[编辑:遗留问题]--

这里有一些例子:

顶部是带有 alpha 视频的 GLSurfaceView,底部是自定义 GLTextureView,两者都在 horizontalView 中。 顶部似乎是我想要的好!但是当我向右滚动时检查一下:

根据需要隐藏底部时,顶部仍然出现!

【讨论】:

  • 您不应该清除 (.0f, .0f, .0f, .0f) 吗?在您的混合情况下,alpha 不会设置为 0。或者可能只是在您现在拥有的情况下禁用混合。
  • 我刚试过GLES20.glClearColor(.0f, .0f, .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); 不工作(黑色背景)
  • 所以我假设黑色背景是整个 GL 表面视图,蓝色背景是其他视图。如果是这样,您看到的是正确的,但您需要一种方法来启用透明的 GL 表面视图,以便它与管道中的其他视图混合。尝试在网上搜索一下。也许只有一个属性,比如 opaque 需要禁用......
  • stackoverflow.com/questions/5391089/… 看起来很有希望..
  • 感谢@MaticOblak,我将发布一份简历,说明我为解决此问题所做的所有建议
【解决方案2】:

只是快速浏览一下您的代码似乎已经有很多奇怪的和平。我希望您至少包含您的顶点数据(位置和纹理坐标)。首先请检查线路

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 仅绘制框架的顶部(颜色)以获得预期结果(透明部分应为黑色)。然后使用alphaTextureCoordinatesgl_FragColor = vec4(alpha, alpha, alpha, 1.0) 检查alpha 部分,这应该会产生一个灰度图像,其中白色是完整的alpha,黑色不是alpha。在所有这些都得到确认后,尝试按照上面的说明将它们放在一起。

要使表面视图与其他视图混合,您需要设置透明度,并且需要用透明颜色填充透明像素。

由于您使用的是混合,因此您需要清除背景以清除颜色(.0f, .0f, .0f, .0f)。在您的情况下,简单地禁用混合应该会产生相同的结果。

这样做之后,您仍然会看到黑色背景,因为表面视图不会隐式与其他视图(背景)混合,并且仅使用 RGB 部分来填充渲染视图。要启用透明度,您应该查看其他一些 answersthis one

【讨论】:

  • 谢谢,为什么要.b? ,因为蒙版是灰度蒙版,所以蓝色、红色和绿色具有相同的值,并且可以确保计算类似于 alpha = (.r +.g + .b) / 3 但是你可以看到三个是否相同价值是没必要做的!为什么是 IF ?其实我真的不需要!目标是最后只有上部,ANDROID 视图应该是一半高度以隐藏无用的!
  • 我是这么认为的,但通常开发人员使用“.x”或“.r”作为第一个组件。由于您使用了第三个组件,因此它可能具有重要意义,因此最好问一下。如果您在尝试应用这些程序后发现任何困难或发现一些意外结果,请告诉我们,以便我们进一步提供建议。
  • 我发现了我在执行你的答案时遇到的问题:我忘记将颜色 Y 坐标也修改为:colorTextureCoordinates = vec2(vTextureCoord.x, vTextureCoord.y*.5);。阿尔法问题仍然令人遗憾
猜你喜欢
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多