Войти
ПрограммированиеФорумГрафика

Альфа-смешение в зависимости от значения в приёмнике

#0
18:58, 7 авг. 2018

Привет.
Нужно сформировать рендер-таргет RT в RGBA, DX9, следующим образом:
ablend | Альфа-смешение в зависимости от значения в приёмнике

Сначала выводится объекта A без альфа-бленда. Затем выводится объект B с альфа-блендом но:
поверх пикселей объекта A смешение есть, иначе (там где чёрное) цвет и альфа канал пишутся напрямую в RT.
После рисуется объект C (цифры) со стандартным смешением.

Далее это уходит на аппаратный микшер, повлиять на который я не могу.

Прочитать содержимое приёмника (RT) нельзя.
Решение приходит только в лоб:
1. Отрисовать A, полученный RT сделать как текстуру-шаблон.
2. Сменить RT, опять отрисовать A.
3. Отрисовать B, используя текстуру-шаблон, смешивая или не смешивая пиксели B в шейдере.
4. Поверх всего этого отрисовать C.

Делал ли кто-нибудь такое смешение (учитывая значение в приёмнике) или видел материалы по этой теме?
Буду благодарен.


#1
19:02, 7 авг. 2018

я так и не понял, чем обычный альфа-бленд не подходит

#2
19:02, 7 авг. 2018

Ничего не понятно. Лучше кодом покажи, какой блендстейт устанавливаешь для А, В, С, и что именно не устраивает на выходе.

#3
19:05, 7 авг. 2018

Для B блендинг включен. Но в этом случае часть B смешается с чёрным цветом. А мне нужна прямая запись (по чёрному).

#4
19:08, 7 авг. 2018

Кодом:
Destination = (Destination.a != 0) ? AlphaBlend(Source,Destination) : Source.

#5
19:09, 7 авг. 2018

Kroll
Стенсил?

#6
19:12, 7 авг. 2018

Сделай RT с текущей текстурой, и со стенсил буфером, и рисуй в 2 этапа.
Сначала просто проверяй стенсил буфер, там где уже нарисовано - рисуй с альфаблендом.
Потом второй раз рисуй то же самое, но теперь без альфабленда, и там, где уже не нарисовано + инвертируй стенсил в этом проходе.

#7
19:14, 7 авг. 2018

Kroll
Во-первых - можно исходную задачу? Потому что есть подозрение, что она вчистую решается pre-multiplied alpha, потому что та ассоциативна.

> со стандартным смешением
Это что такое? C=srcС*srcA+dstC*(1-srcA)?

Это я к тому, что ИМХО, по умолчанию стоит использовать как раз PMA (C=srcС+dstC*(1-srcA)), если нет веских оснований для обратного.

RT изначально залит (0,0,0,0)?

Тогда:
1. Рисуем B, без бленда.
2. Рисуем A поверх B, используя dst в качестве альфы (glBlendFunc(*,GL_ONE_MINUS_DST_ALPHA) или её DirectX эквивалент).
3. Рисуем C поверх этого, с "обычным блендом".

#8
19:21, 7 авг. 2018

Исходная задача такая:
Нужно на некий аппаратный микшер подать отрисованную сцену в виде битмапы с альфа-каналом. Микшер смешает её с видео потоком.
Всё хорошо, кроме полупрозрачных объектов, которые частично лежат на уже отрисованной части RT, а частично на пустой.

#9
19:22, 7 авг. 2018

В blend операции использую alpha_blend_max для операнда альфы.
Залит не чёрным с альфой=0. Но можно и чёрным, если найдётся решение.

#10
19:59, 7 авг. 2018

Kroll
> это уходит на аппаратный микшер, повлиять на который я не могу
А что именно он делает? Т. е. как он смешивает (формула)?

Если у него PMA-блендинг (или ему можно его выставить), тогда халява. Блендим C поверх B поверх A поверх RT (все через PMA), и отдаём микшеру.
Для Lerp-блендинга (C=srcС*srcA+dstC*(1-srcA)) решение из #7 вроде работает.
Псевдокод:

clear_rendertarget(RGBA(0,0,0,0)); // RT=0,0,0,0
set_render_state(D3DRS_SRCBLEND,D3DBLEND_ONE);
set_render_state(D3DRS_DSTBLEND,D3DBLEND_ZERO);
drawB(); // RT=colorB,alphaB
set_render_state(D3DRS_SRCBLEND,D3DBLEND_INVDESTALPHA);
set_render_state(D3DRS_DSTBLEND,D3DBLEND_DESTALPHA);
drawA(); // RT=colorB*alphaB+colorA*(1-alphaB),alphaB+alphaA-alphaA*alphaB
set_render_state(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
set_render_state(D3DRS_DSTBLEND,D3DBLEND_INVSRCALPHA);
drawC(); // Blend C over the previous RT.
send_to_hardware_mixer(rendertargrt);

#11
20:03, 7 авг. 2018

FordPerfect
Да, lerp-blend.

#12
20:04, 7 авг. 2018

Спасибо всем за мысли.
Надо подумать.

ПрограммированиеФорумГрафика

Тема в архиве.