Есть буфер с альфа каналом, ну и цвета с альфа составляющей.
Не могу их правильно смешать
Уже весь мозг себе сломал.
Основная идея в том, что если буфер залит непрозрачным цветом, то цвета должны смешиваться с фоном,
а если фон прозрачный, то не должны.
Первый используется для отображения на экране, второй для генерации прозрачных картинок.
Пока что велосипед выглядит так:
static AGG_INLINE void blend_pix(value_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover=0)
{
if(alpha==0)return;
calc_type a=p[Order::A];
if(a==0)
{
p[Order::R]=(value_type)cr;
p[Order::G]=(value_type)cg;
p[Order::B]=(value_type)cb;
p[Order::A]=(value_type)alpha;
return;
}
calc_type r = p[Order::R];
calc_type g = p[Order::G];
calc_type b = p[Order::B];
p[Order::R] = (value_type)((cr*alpha*base_mask+r*a*(base_mask-alpha))/base_mask/base_mask);
p[Order::G] = (value_type)((cg*alpha*base_mask+g*a*(base_mask-alpha))/base_mask/base_mask);
p[Order::B] = (value_type)((cb*alpha*base_mask+b*a*(base_mask-alpha))/base_mask/base_mask);
p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift));
}
Использую agg. Но это в принципе не важно. Давайте будем считать
что цвета у нас от 0 до 1. И альфа канал тоже от 0 до 1.
r,g,b,a — цвет фона.
cr,cg,cb,ca — накладываемый сверху цвет.
Код у нас получается такой:
if(ca==0)return;
if(a==0)
{
r=cr;
g=cg;
b=cb;
a=ca;
return;
}
r=cr*ca+r*a*(1.0-ca);
g=cg*ca+g*a*(1.0-ca);
b=cb*ca+b*a*(1.0-ca);
a=ca+a-ca*a;
Первый if: Если новый цвет целиком прозрачный, то он не оказывает никакого влияния на буфер, даже если тот тоже целиком прозрачный.
Второй if — это костыль.
Посмотрим на выражение: r=cr*ca+r*a*(1.0-ca);
Допустим буфер у нас целиком прозрачный, тогда правая часть суммы r*a*(1.0-ca)=0.
Допустим мы накладываем белый цвет, с прозрачностью 0.5. Тогда левая часть суммы, превращает наш цвет из белого в серый.
Хотя по идее он должен был остаться белым с альфа каналом 0.5.
Эту формулу взял с
википедии. Мне она показалась наиболее разумной в моём случае.
Формула смешивания альфа канал хз почему такая.
Взял с той же википедии и в том же agg часто используется именно в таком виде.
Что она значит, так и не понял
Для меня это "суммируем значение прозрачности, главное чтобы она не превысила максимальное значение"
В чём проблема с моим кодом?
1. Хотелось бы убрать костыли и не изобретать велосипед.
2. Хотелось бы добиться непрерывности функций.
Ещё раз приведу формулу: r=cr*ca+r*a*(1.0-ca);
Допустим буфер у нас "почти прозрачный" a — стремится к нулю, тогда правая часть суммы r*a*(1.0-ca) тоже стремиться к нулю.
И мы получаем туже проблему, что белый полупрозрачный цвет превращается в грязно-серый.
3. Хотелось бы понять как именно складывать альфа канал.