【问题标题】:OpenGL transparent images have black in themOpenGL透明图像中有黑色
【发布时间】:2012-05-09 14:46:11
【问题描述】:

我正在开发一款适用于 Android 的游戏,我想知道为什么每当我绘制具有透明度的图像时,似乎总是在透明部分添加了一些黑色。这一切都发生了,让我的一些效果看起来很奇怪。

这是一个例子。这两个圆圈只是带有模糊的白色图像,但是当一个与另一个重叠时,您可以看到它有阴影。如果我在 Inkscape 中重叠两个圆圈,我会在它们重叠的地方得到纯白色。

我正在使用

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

为了我的混合。

知道为什么会发生这种情况以及如何避免它吗?

编辑:我唯一能想到的是这两个图像具有相同的 z,所以它们可能只与背景混合而不是相互混合?

编辑: 我变了

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_DST_ALPHA);

这是我正在寻找的结果。

现在唯一的问题是,我拥有的透明黑色的透明图像被忽略了,这是有道理的,因为我认为目标 alpha 为 1。为什么一个减号源会添加那个灰色?

【问题讨论】:

  • 关于您编辑中的问题,您是不正确的,这是不可能的。
  • 就个人而言,我认为阴影看起来很棒。但这只是我。

标签: android opengl-es alpha overlap blending


【解决方案1】:

您确定您的内容正确吗?如果您不希望圆圈产生任何黑色,则图像中的颜色值应该是完全白色的,并且 Alpha 通道应该定义圆圈的形状。现在看起来图像有一个带有 Alpha 通道的白色圆圈,颜色值逐渐变为零,这会导致光晕。

【讨论】:

  • 是的,我的图像是全白的,模糊和形状由 Alpha 通道定义。
  • 是的,但是您使用的是什么库?它肯定会预乘你的 alpha
【解决方案2】:

您是否使用线性采样?我的想法可能是,如果您的图像非常小(尺寸小于 30-40 像素),您可能会在圆内部(alpha = 1)和圆外部(alpha = 0)。这将为您提供导致模糊效果的中间 alpha 值。

当你绑定了圆形纹理时,试试下面的代码:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

也许您可以托管您正在使用的实际纹理,以便我们对其进行检查?如果这没有帮助,也请发布您的绘图代码。

【讨论】:

  • 我想你不明白。我想要模糊,它在原始图像中。原件中没有的是它重叠的黑色部分。我会在问题中发布原件。
  • @EmbMicro 哦,对不起,我误会了。如果您使用深度测试,您首先绘制了原始图像中的这两个圆圈中的哪一个,以及您的深度缓冲区设置是什么样的?
【解决方案3】:

我想出了如何解决它。

我变了

GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);

事实证明,Android 会在加载 PNG 图像时预乘其纹理的 alpha(使白色变为灰色)。

我加了

vColor.r = vColor.r * vColor.a;
vColor.g = vColor.g * vColor.a;
vColor.b = vColor.b * vColor.a;

到我的顶点着色器为我的其他颜色做乘法。

【讨论】:

  • 你可以把 alpha 分出来。阅读下面我的评论
【解决方案4】:

您也可以除以 Alpha,因为问题是,当您导出纹理时,图像处理软件可能会预乘您的 Alpha 通道。我最终将 alpha 分割到我的片段着色器中。以下代码是 HLSL,但您可以轻松地将其转换为 GLSL:

float4 main(float4 tc: TEXCOORD0): COLOR0
{
    float4 ts = tex2D(Tex0,tc);

    //Divide out this pre-multiplied alpha
    float3 outColor = ts.rgb / ts.a;

    return float4(outColor, ts.a);
}

请注意,此操作是有损的,非常有损,即使在此类情况下它很可能就足够了,但它不是一个通用的解决方案。在您的情况下,您可以完全忽略颜色并在片段着色器中提供原始 alpha 和白色,例如return float4(1,1,1,ts.a);(转换为 GLSL)

【讨论】:

    猜你喜欢
    • 2017-06-04
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2013-08-21
    • 2015-08-12
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多