如何使用透明纹理和透明色混合?

问题描述 投票:0回答:1

我正在使用OpenGL ES 3.我想绘制透明图像。图像的一些像素可具有0%至100%的透明度。我还希望能够设置一个argb值来改变整个图像的颜色和透明度。

我最终得到了以下解决方案。

渲染:

GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);

GL.Uniform4(shader.UniformColor, color);
GL.BindTexture(TextureTarget.Texture2D, sprite.TextureId);
...

片段着色器:

void main()
{
    fragColor = texture(text, textureCoordinate) * color;
}

问题是,当我设置透明色时,混合错误,图像变亮。它似乎没有正确地与背景混合。当我使用BlendingFactorSrc.SrcAlpha时,透明度是正确的,但图像周围有一个黑色边框。

有没有人有这个问题的解决方案?我已经研究了很多,黑暗边界的解决方案是使用混合源因子1。但如上所述,我得到了另一个问题。

谢谢你的帮助!

编辑:这是问题的一个例子:https://i.stack.imgur.com/LAw3K.png

shader alphablending opengl-es-3.0
1个回答
1
投票

有两个不同的问题。 1:似乎有必要在将图像数据加载到纹理之前处理它。我遇到了“预乘alpha”,这在我的案例中似乎是必要的。您基本上将每个rgb值乘以alpha值。我仍然不知道为什么它必须那么复杂,你不能直接在opengl中设置它:

private void PremultiplyAlpha(byte[] data)
{
    for (int i = 0; i < data.Length; i += 4)
    {
        int alpha = data[i + 3]; // A
        float factor = alpha > 0 ? 255f / alpha : 1f;

        data[i] = (byte)(data[i] * factor); // R
        data[i + 1] = (byte)(data[i + 1] * factor); // G
        data[i + 2] = (byte)(data[i + 2] * factor); // B
    }
}

…

 byte[] data = GetPixelArray(bitmap);

 PremultiplyAlpha(data);

 GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, OpenTK.Graphics.ES30.PixelFormat.Rgba, PixelType.UnsignedByte, data);

2:当纹理以不同比例渲染并使用mipmap时,仍然存在边框。我不得不将以下设置从NearestMipmapLinear更改为Nearest:

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMagFilter.Nearest);// (int)All.NearestMipmapLinear);

我可以使用以下混合功能:

GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
© www.soinside.com 2019 - 2024. All rights reserved.