Как использовать смешивание с прозрачными текстурами и прозрачным цветом? - PullRequest
0 голосов
/ 19 апреля 2019

Я использую OpenGL ES 3. Я хочу рисовать прозрачные изображения. Некоторые пиксели изображения могут иметь прозрачность от 0% до 100%. Я также хочу иметь возможность установить значение argb для изменения цвета и прозрачности всего изображения.

Я получил следующее решение.

Rendering:

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, прозрачность правильная, но вокруг изображения темная рамка.

У кого-нибудь есть решение этой проблемы? Я много исследовал, и решением для темной границы было использование исходного фактора смешения один. Но, как описано выше, у меня возникает еще одна проблема.

Спасибо за вашу помощь!

Редактировать: вот иллюстрация проблемы: https://i.stack.imgur.com/LAw3K.png

1 Ответ

1 голос
/ 20 апреля 2019

Было 2 разных проблемы.

1: кажется, что необходимо обработать данные изображения перед загрузкой в ​​текстуру. Я наткнулся на «предварительно умноженную альфу», которая, как мне кажется, необходима в моем случае. Вы в основном умножаете каждое значение RGB на альфа-значение. Я до сих пор не знаю, почему это должно быть так сложно, и вы не можете установить его напрямую в 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);
...