Почему при рисовании 8-битной текстуры OpenGL рисует черные пиксели вместо прозрачных? - PullRequest
5 голосов
/ 11 января 2012

Настройка OpenGL:

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_DEPTH_TEST );
glEnable( GL_TEXTURE_2D );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glClearColor( 0.0, 1.0, 1.0, 1.0 );

Инициализация текстуры:

// 16x16 X pattern
uint8_t buffer[ 16*16 ] =
{
    255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
    0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
    0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0,
    0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0,
    0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
    0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0,
    0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0,
    0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0,
    255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255,
};

GLuint texture_id;
glGenTextures( 1, &texture_id );
glBindTexture( GL_TEXTURE_2D, texture_id );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

Текстуры отрисовываются в виде четырехугольников с использованием glBegin / glEnd,Цвет каждой вершины - белый с полной альфа-версией: {r = 255, g = 255, b = 255, a = 255}.

Вот пример сцены.Фотография и сыр загружены из изображений PNG.У сыра есть прозрачные отверстия, которые показывают фотографию и фон позади этого.X-образ, который я ожидал, тоже будет прозрачным:

Example

Почему четырехугольник черный, а не прозрачный, как я могу исправить свой код, чтобы нарисовать то, что я ожидал?

Этот вопрос может быть похожим, но пока я не могу применить краткий ответ к моей текущей проблеме.

Обновление: я думаю, что решил его, благодаря ответамниже.Я изменил ...

glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer );

на

glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer );

... что дает желаемый результат.

Ответы [ 4 ]

6 голосов
/ 11 января 2012

@ Дитрих Эпп ответил почти правильно, только тот формат, который вы ищете - GL_ALPHA:

glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);

Затем установите функцию смешивания на glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); или glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);, в зависимости от того, предварительно ли умножены ваши значения. Наконец, что не менее важно, установите текстуру среды в GL_MODULATE

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

Теперь вы можете установить цвет 'X' с помощью glColor.

Другой подход заключается не в смешивании, а в альфа-тестировании.

3 голосов
/ 11 января 2012

Изменить GL_RGBA8 (что делает изображение в градациях серого с без альфа-канала ) на GL_INTENSITY:

glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY, 16, 16, 0,
             GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer);

Формат GL_RGBA8, созданный из GL_LUMINANCE,дает пиксели вида (Y, Y, Y, 1), но GL_INTENSITY с GL_LUMINANCE дает (Y, Y, Y, Y).

Вы также можете изменить режим смешивания, чтобы принять предварительно умноженную альфа, например, изменить

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

до:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Альтернатива:

Вы также можете использовать GL_ALPHA, а затем использовать обычный режим смешивания для не-предварительно умноженного альфа:

glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0,
             GL_ALPHA, GL_UNSIGNED_BYTE, buffer);

Альтернатива # 2:

Вы можете продолжать использовать GL_LUMINANCE и изменять режим смешивания.

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);

Это имеетнедостаток в том, что вы не можете раскрасить текстуру, не используя что-то вроде glBlendColor (которое не является частью заголовков OpenGL, которые поставляются с MSVC, поэтому вы должны использовать GLEW или что-то подобное):

glBlendColor(...);
glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);

Альтернатива # 3:

Используйте OpenGL 3 и измените ваш фрагментный шейдер для обработки одноканальных текстур желаемым способом.

3 голосов
/ 11 января 2012

Becuse яркость - это цвет, а прозрачность (альфа) - это не цвет.

Если вам нужна прозрачность, используйте другой формат - GL_LUMANANCE_ALPHA или что-то подобное, и сохраняйте прозрачность в другом канале.

Кроме того, это уже объяснено в документации .

GL_LUMINANCE

Каждый элемент имеет одно значение яркости. GL преобразует его в число с плавающей запятой, затем собирает его в элемент RGBA, трижды реплицируя значение яркости для красного, зеленого и синего и добавляя 1 для альфа . Каждый компонент затем умножается на масштабированный коэффициент со знаком GL_c_SCALE, добавляется к смещению со знаком GL_c_BIAS и фиксируется в диапазоне [0,1] (см. GlPixelTransfer).

- изменить -

Есть ли способ сохранить 8 бит на пиксель и добиться того же эффекта?

Я думаю, что вы могли бы "сказать" OpenGL, что исходное изображение имеет индексированный цвет, а затем настроить правильную палитру RGBA (где для каждого элемента R == G == B == A == index). Подробнее см. glPixelTransfer и glPixelMap.

0 голосов
/ 31 января 2019

Восемь битовых изображений не используют цвета, они имеют цветовую палитру.Ноль представляет индекс 0 цветовой палитры для этого изображения, который будет содержать 256 цветов.Восемь битовых изображений не имеют альфа-канала для прозрачности.Изображение PNG, которое вы использовали, имеет альфа-канал.Это будет 32-битное изображение, которое имеет 8 бит для красного, 8 бит для зеленого, 8 бит для синего (24 бита для цвета) и 8 бит для альфа.Вы смешиваете два формата.

...