【问题标题】:How can I get Alpha blending transparency working in OpenGL ES 2.0?如何在 OpenGL ES 2.0 中获得 Alpha 混合透明度?
【发布时间】:2013-06-08 22:05:04
【问题描述】:

我正在将一些代码从 OpenGL ES 1.x 移植到 OpenGL ES 2.0,我正在努力让透明度像以前一样工作;我所有的三角形都被渲染成完全不透明的。

我的 OpenGL 设置有以下几行:

// Draw objects back to front
glDisable(GL_DEPTH_TEST);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glDepthMask(false);

我的着色器看起来像这样:

attribute vec4 Position;
uniform highp mat4 mat;
attribute vec4 SourceColor;
varying vec4 DestinationColor;

void main(void) {
  DestinationColor = SourceColor;
  gl_Position = Position * mat;
}

还有这个:

varying lowp vec4 DestinationColor;

void main(void) {
  gl_FragColor = DestinationColor;
}

可能出了什么问题?

编辑:如果我按照keaukraine below 的建议将片段着色器中的 alpha 手动设置为片段着色器(或者实际上是顶点着色器)中的0.5,那么我会得到透明的一切. 此外,如果我将传递给 OpenGL 的颜色值更改为浮点数而不是无符号字节,则代码可以正常工作。

因此,将颜色信息传递给 OpenGL 的代码似乎有问题,我仍然想知道问题出在哪里。

我的顶点是这样定义的(与 OpenGL ES 1.x 代码相同):

typedef struct
{
  GLfloat x, y, z, rhw;
  GLubyte r, g, b, a;
} Vertex;

我使用以下代码将它们传递给 OpenGL(类似于 OpenGL ES 1.x 代码):

glBindBuffer(GL_ARRAY_BUFFER, glTriangleVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * nTriangleVertices, triangleVertices, GL_STATIC_DRAW);
glUniformMatrix4fv(matLocation, 1, GL_FALSE, m);
glVertexAttribPointer(positionSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, x));
glVertexAttribPointer(colorSlot, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, r));
glDrawArrays(GL_TRIANGLES, 0, nTriangleVertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);

上面有什么问题?

【问题讨论】:

    标签: opengl-es opengl-es-2.0 transparency alpha


    【解决方案1】:

    我怀疑与您的片段着色器不同的 DestinationColor 始终包含 Alpha 通道的 0xFF?如果是这样,那是你的问题。尝试改变它,让 alpha 实际变化。

    更新:我们找到了 2 个很好的解决方案:

    1. 对片段着色器中提供给 DestinationColor 的变量使用浮点数而不是无符号字节。

    2. 或者,正如 GuyRT 指出的那样,您可以将 glVertexAttribPointer 的第四个参数更改为 GL_TRUE,以告诉 OpenGL ES 在将值从整数转换为浮点数时对其进行规范化。

    【讨论】:

    • 我认为它实际上总是包含 1,但你是对的,一旦它到达片段着色器就错了。 (见上面的编辑。)有什么想法吗?
    • 输入颜色值必须是 0.0 到 1.0 范围内的浮点数。因为您使用的是字节,所以所有大于 0 的整数值都被转换为 1.0 及以上的值,饱和到 1.0 以使您完全不透明。
    • 谢谢!我想这就是正在发生的事情,但我没有意识到这仅仅是因为您不能在 OpenGL ES 2.0 中使用无符号字节作为颜色。如果您编辑您的答案以包含此信息,我将删除我的答案并接受您的。
    • 您可以使用字节来表示颜色。只需将glVertexAttribPointer 的第四个参数更改为GL_TRUE,这些值就会按照您最初的预期进行标准化。
    【解决方案2】:

    要调试这种情况,您可以尝试设置常量 alpha 并查看它是否有所不同:

    varying lowp vec4 DestinationColor;
    
    void main(void) {
      gl_FragColor = DestinationColor;
      gl_FragColor.a = 0.5; /* try other values from 0 to 1 to test blending */
    }
    

    此外,您应该确保选择带有 alpha 通道的 EGL 配置。

    别忘了在片段着色器中为浮点数指定精度!阅读 OpenGL GL|ES 2.0 的规范(http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf 第 4.5.3 节),请参阅此答案:https://stackoverflow.com/a/6336285/405681

    【讨论】:

    • 谢谢。那很有帮助。看起来我在传递无符号字节的方式上做错了什么。 (见问题编辑。)有什么想法吗?
    【解决方案3】:

    您的颜色顶点属性值没有被规范化。这意味着顶点着色器会看到该属性的值在 0-255 范围内。

    glVertexAttribPointer 的第四个参数更改为GL_TRUE,值将按照您最初的预期进行归一化(缩放到0.0-1.0 范围)。

    http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml

    【讨论】:

    • 当我意识到我的代码中的一个错误导致该标志完全未定义时,可能不像我那样愚蠢!
    猜你喜欢
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    相关资源
    最近更新 更多