如何使用透明纹理和透明颜色的混合?
How to use blending with transparent textures and transparent color?
我正在使用 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
有 2 个不同的问题。
1:似乎有必要在将图像数据加载到纹理之前对其进行处理。我遇到了 "premultiplied 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);
我正在使用 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
有 2 个不同的问题。
1:似乎有必要在将图像数据加载到纹理之前对其进行处理。我遇到了 "premultiplied 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);