Хороший способ борьбы с альфа-каналами в 8-битном растровом изображении?- OpenGL - C ++ - PullRequest
1 голос
/ 20 июня 2011

Я загружаю растровые изображения с OpenGL, чтобы текстурировать трехмерную сетку.Некоторые из этих растровых изображений имеют альфа-каналы (прозрачность) для некоторых пикселей, и мне нужно найти лучший способ

  1. получить значения прозрачности для каждого пикселя

и

  1. визуализируйте их с примененной прозрачностью

У кого-нибудь есть хороший пример этого?OpenGL поддерживает это?

Ответы [ 2 ]

5 голосов
/ 20 июня 2011

Прежде всего, обычно лучше преобразовать ваши растровые данные в 32-битные, чтобы каждый канал (R, G, B, A) получал 8 бит. При загрузке текстуры укажите 32-битный формат.

Затем при рендеринге вам нужно будет glEnable(GL_BLEND); и установить функцию смешивания, например: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);. Это говорит OpenGL смешивать RGB текстуры с фоном, используя альфа вашей текстуры.

Если вы делаете это с трехмерными объектами, вы также можете отключить выборку задней поверхности (чтобы вы могли видеть заднюю часть объекта через переднюю часть) и отсортировать треугольники задом наперед (чтобы смеси происходят в правильном порядке).

Если ваше исходное растровое изображение является 8-разрядным (т. Е. С использованием палитры с одним цветом, указанным в качестве маски прозрачности), то, вероятно, проще всего преобразовать это в RGBA, установив значение альфа-канала в 0, когда цвет соответствует вашей маске прозрачности .

Некоторые подсказки, чтобы вещи (возможно) выглядели лучше:

  • Ваш альфа-канал будет делом "все или ничего" (либо 0x00, либо 0xff), поэтому примените некоторый алгоритм размытия, чтобы получить более мягкие края, если вы к этому стремитесь.
  • Для текселей (текстур-пикселей) с альфа-нулем (полностью прозрачный) замените цвет RGB ближайшим непрозрачным текселем. Когда текстурные координаты интерполируются, они не будут смешиваться с исходным цветом прозрачности вашего BMP.
1 голос
/ 20 июня 2011

Если ваше растровое изображение является 8-битным одиночным каналом, то оно либо в оттенках серого, либо использует палитру. Сначала вам нужно преобразовать данные растрового изображения в формат RGBA. Для этого вы выделяете достаточно большой буфер для размещения 4-канального растрового изображения размеров исходного файла. Затем для каждого пикселя растрового изображения используйте значение этого пикселя в качестве индекса в палитре (посмотрите таблицу) и поместите это значение цвета в соответствующий пиксель в буфере RGBA. После завершения загрузите в OpenGL, используя glTexImage2D .

Если ваш графический процессор поддерживает фрагментные шейдеры (весьма вероятно), вы можете выполнить это преобразование LUT в шейдере: загрузить 8-битный пиксель в виде 2D-текстуры GL_RED или GL_LUMINANCE. И загрузите палитру в виде 1D текстуры GL_RGBA. Затем во фрагментном шейдере:

uniform sampler2D texture;
uniform sampler1D palette_lut;

void main()
{
    float palette_index = texture2D(texture,gl_TexCoord[0].st).r;
    vec4 color = texture1D(palette_lut, palette_index);
    gl_FragColor = color;
}

Смешанный рендеринг конфликтует с алгоритмом Z-буфера, поэтому вы должны отсортировать геометрию задом наперед, чтобы все выглядело правильно. Пока это влияет на объекты в целом, это довольно просто, но это становится утомительным, если вам нужно отсортировать грани сетки, визуализирующей каждый кадр. Методом, позволяющим избежать этого, является разбиение сеток на выпуклые подсетки (конечно, уже выпуклая сетка не может быть разбита дальше). Затем используйте следующий метод:

  • Включить отбор лица
  • для выпуклой_субмешь в отсортированном виде (сетки, далеко до почти):
    • установить обрезку граней на передние грани (т.е. задняя сторона будет обработана)
    • рендеринг выпуклой_субмеш
    • установить отбор граней на спину граней (т.е. отрисовывается передняя сторона)
    • сделать снова выпуклый_субмеш
...