Wohlstand
@Wohlstand
Инженер-программист С++

Как определять прозрачные области спрайта, используя маску?

У нас есть два изображения:
исходное, с чёрным фоном: goomba1.gif
и его маска, с белым фоном: goomba1-mask.gif

Мне нужно:
Получить вместо чёрного фона прозрачность так, чтобы в случае чёрных контуров у спрайта, они отображались. Потому что, если выполнять просто хромакей по чёрному фону, то контуры тоже будут прозрачными. Известно, что можно выйти из ситуации рисованием контуров ЧУТЬ-более светлым, чем чёрным (например, фон #000000 а контуры #000001), но это не подходит, потому проект планируется для пользовательских спрайтов. Прозрачность должна проявляться именно там, где на маске белый фон совпадает с чёрным фоном на оригинале.
goomba1.gif + goomba1-mask.gif = goomba1_2.png

В альфа-канале нет необходимости.
Использую для работы библиотеку SDL на С++.
________________________________________________________________________

Хотя есть предположение:
Цвет на маске: должен вычитать цвет из альфа-канала соответствующего пикселя на каждом изображени, но на исследуемом ПО видел, что если под маску попадал не чёрный цвет, он начинает смешиваться с фоном и получается грязь:

Эксперимент в исследуемом ПО с неправильной маской:
Исходник и маска:

background-9.gifbackground-9m.gif


Результат:

Scr_2014.02.19_23-32-28-560.jpg

UPD: Спустя время выяснил, какой на самом деле применяется алгоритм рисования таких изображений:

Для этого использовался алгоритм битовой маски.

т.е.:
  • Сначала отрисовывается маска с побитовым "И" попиксельно с экранными пикселями.
  • Затем в том же месте отрисовывется сама картинка, но с побитовым ИЛИ попиксельно с экранными пикселями

Такой алгоритм применялся в исследуемой программе по той причине, что VisualBasic 6, на котором последняя была написана, штатно не поддерживал альфа-канал и отрисовку прозрачных изображений. Почему даже в некоторых примерах и туториалах применялся именно этот метод. В своём движке я применяю PNG-картинки, а старые преобразую смешивая с серым фоном, назначая альфа-канал в зависимости от суммы пикселей маски и самой картинки.

Так-же можно применять маску в качестве инвертированного альфа-канала, однако если маска неправильная (пользователи старого движка очень часто делали "ленивые" маски - скопировали саму картинку, просто залив фон белым), то картинка получается кривой с полупрозрачностями разного уровня (что строго требует использование правильной маски). В итоге когда я сделал конвертер изображений с масками в PNG, так же сделал и утилиту, которая фиксит "ленивые" маски автоматически.
  • Вопрос задан
  • 4088 просмотров
Решения вопроса 1
Teivaz
@Teivaz
Шейдером в openGL это решается элементарно.
Передаём в шейдер обе текстуры. Из первой текстуры берём r, g, b. Потом вычисляем яркость второй текстуры в точке и в прозрачку стави один минус это значение.
vec4 tex1 = texture2D(texture1, position);
vec4 tex2 = texture2D(texture2, position);
float luma2 = (tex2.r + tex2.g + tex2.b)/3.0;
gl_FragColor = vec4(tex1.r, tex1.g, tex1.b, 1.0 - luma2);
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
xytop
@xytop
PHP/RoR web dev & tech lead
А почему-бы не искать на маске белый цвет и не делать цвет в тех же координатах на оригинале прозрачным?
Про контуры не понял.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы