Войти
ПрограммированиеФорум2D графика и изометрия

Блендинг по альфа-маске в Direct3D (2 стр)

Страницы: 1 2 3 4 Следующая »
#15
13:09, 27 дек 2013

x
Супер! SRC.R'G'B' * DEST.A, это и получается SRC.RGB * SRC.A * DEST.A, перемножение альфы, которое требуется. Прости, что туплю, для меня ново это всё.

MrShoor
> Ну глядя на видео - похоже тебе нужно стекло строго внуртри дырок? Без нахлеста же?
Ага, стекло строго внутри дырок, но это на тестовых тайлах на видео дырки ровные и симметричные, а в реальном тайлсете (как на картинке в нуль-посте) края стекла могут быть другими, с трещинами, например. Нахлёста, конечно, нет. Тайлы дырок просто выводятся рядом друг с другом, на каждый сверху хочется наложить по его индивидуальной маске индивидуально подогнанный фрагмент спрайта блика. Так, чтобы казалось, что блик цельный для всего стекла и двигался в зависимости от положения камеры.

Твоя концепция ещё не развалилась? Я зацепился за слово "запекать", а сути приёма просто не понял, т.к. не слишком силён в этой кухне. Я раньше D3DX использовал без каких-либо сложных приёмов, просто спрайты с альфой накладывал друг на друга и не парился. А сейчас пытаюсь поднять игру на более серьёзный уровень, перешел на чистый Direct3D и пытаюсь сориентироваться чего я тут вообще могу.

Прошлая публичная версия полтора года назад была: http://www.gamer.ru/nesyt/simulyator-plotoyadnogo-chervya
Но сейчас уже всё по-другому, думаю через месяцок-другой смогу открыть тему в "Проектах".
А про релиз, честно говоря, боюсь думать. Надеюсь летом хоть что-нибудь опубликовать.

#16
13:21, 27 дек 2013

Поход с блендингом сработает только если у тебя в Dest реально сохраняется альфа.

Так если без нахлеста - то я не понял почему нельзя тупо пордяком отрисовки подсовывать блики под накладку?
Буду оперировать картинками из 0 поста.
1. Рисуем травку с букашками
2. Рисуем стекло
3. Рисуем накладку на фон

Почему нельзя так сделать то?

#17
13:36, 27 дек 2013

MrShoor
> почему нельзя тупо пордяком отрисовки подсовывать блики под накладку?
Я думал о такой теме, но мешает этому декор под стеклом. Посмотри на картинку в нуль-посте - у окошка под стеклом есть провода, железки и прочее, что должно перекрываться и стеклом и бликами на стекле.

Можно применить предложенный тобой подход, если разложить окошко на два слоя - нижний декор и накладываемые края со стеклом. Пока считаю это аварийным вариантом, т.к. процесс разрезания на части довольно морочен. Надеюсь получится реализовать всё с маской - это более универсальный подход, который я смогу активно использовать не только на окошках, но на любом объекте в игре, который я захочу сделать бликующим.

#18
13:54, 27 дек 2013

> Я думал о такой теме, но мешает этому декор под стеклом. Посмотри на картинку в нуль-посте - у окошка под стеклом есть провода, железки и прочее, что должно перекрываться и стеклом и бликами на стекле.
Значит все таки нахлест есть. Ну попробуй с альфой, если не получится - будем думать. Можно стенсилом конечно почикать это, правда пропадет антиалиясинг на краях круга... Проще всего конечно мультитекстурированием решить проблему.

#19
20:36, 28 дек 2013

Что-то пока не выходит. :(

Рисую спрайт бликов с premultiplied alpha вот так:

_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

На выходе получаю всё как надо там, где у маски alpha=255, но чем прозрачнее маска, тем темнее результат на выходе (а должен быть прозрачнее). Вот иллюстрация:
SomethingWrong | Блендинг по альфа-маске в Direct3D

Альфа от маски точно прописывается в DEST, т.к. если выводить спрайт блика вот так:

_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);

То, видно, что по альфе из DEST всё хорошо режется. Ну и, конечно, при таком выводе ожидаемо игнорируется альфа из спрайта бликов.
AlphaFromDest | Блендинг по альфа-маске в Direct3D

Premultiplied alpha в спрайте бликов делаю так:

#define D3DCOLOR_ALPHA(x) ((x>>24) & 0xFF)
#define D3DCOLOR_RED(x)  ((x>>16) & 0xFF)
#define D3DCOLOR_GREEN(x) ((x>>8) & 0xFF)
#define D3DCOLOR_BLUE(x) ((x) & 0xFF)

//Перемножение цветовых составляющих текстуры с альфой
void Direct3DEngine::MakePremultipliedAplha(BitmapId id)
{    
  //Получение описателя растра
  auto &bitmap = _bitmaps[id];

  //Выяснение габаритов
  D3DSURFACE_DESC surface;
  bitmap.D3DTexture->GetLevelDesc(0, &surface);

  //Получение доступа к пикселям
  D3DLOCKED_RECT rect;
  bitmap.D3DTexture->LockRect(0, &rect, NULL, NULL);
  D3DCOLOR *pixels= (D3DCOLOR*)rect.pBits;

  //Перемножение цветовых составляющих на альфу
  for(long i=0; i<surface.Width * surface.Height; ++i)
  {
    D3DCOLOR pixel = pixels[i];

    float alpha = (float)D3DCOLOR_ALPHA(pixel) / 255.0f;

    pixels[i] = D3DCOLOR_RGBA(  
                  (char)((float)D3DCOLOR_RED(pixel) * alpha),  
                  (char)((float)D3DCOLOR_GREEN(pixel) * alpha), 
                  (char)((float)D3DCOLOR_BLUE(pixel) * alpha), 
                  D3DCOLOR_ALPHA(pixel));
  }

  //Разблокировка прямого доступа к пикселям
  bitmap.D3DTexture->UnlockRect(0);

  //Перегенерация mip-уровней
  bitmap.D3DTexture->SetAutoGenFilterType(D3DTEXF_ANISOTROPIC);
  bitmap.D3DTexture->GenerateMipSubLevels();
}
    
#undef D3DCOLOR_ALPHA
#undef D3DCOLOR_RED
#undef D3DCOLOR_GREEN
#undef D3DCOLOR_BLUE

Есть какие-нибудь идеи? Что я могу делать не так и как это можно проверить?

P.S. На разных картинках блик по-разному внутри себя сдвинут, это не ошибка, просто скриншоты делал с разных положений камеры.

#20
20:52, 28 дек 2013

>Есть какие-нибудь идеи?
Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного варианта (первые две картинки)?
Выведи его нормально.
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

#21
21:19, 28 дек 2013

Допустим в блике у тебя записана аргб:
0.25, 1.0, 1.0, 1.0
после премульта у тебя такой цвет
0.25, 0.25, 0.25, 0.25

в маске (там где серый фон) у тебя я так понимаю
0.0, 0.0, 0.0, 0.0

ну и допустим у тебя серый фон (тут альфа в аргб из маски взята)
0.0, 0.5, 0.5, 0.5

итак srcColor после
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
будет
0.25, 0.0, 0.0, 0.0
тут все верно.

а dstColor после
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
будет 1.0-0.25 = 0.75(это инвертированная альфа), 0.5 * 0.75 = 0.375 сооответственно:
0.0, 0.375, 0.375, 0.375

То есть видим, что цвет стал темнее. Соответственно не нужно умножать ни на какие альфы. Нужно просто D3DBLEND_ONE.
Попробуй переписать вот так:
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

#22
21:57, 28 дек 2013

MrShoor
Метод тыка ок.

Kozinaka
Там есть ещё проблема, альфа-тест нужно включать.

#23
22:16, 28 дек 2013

x
> Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного
> варианта (первые две картинки)?
Ну, у в предумноженном варианте цветовые составляющие перемножились с альфой, там где альфа была меньше 1, там при прямом выводе цвета стали темнее.

MrShoor
> _d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
> _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

УРРРРА! ПОЛУЧИЛОСЬ!

Success | Блендинг по альфа-маске в Direct3D

x, MrShoor, спасибо вам огромное за помощь!

#24
22:27, 28 дек 2013

Kozinaka
>УРРРРА! ПОЛУЧИЛОСЬ!
На самом деле нет. Твои блики на данной картинке прибавляются к фону. Обычная прозрачность работает не так.

#25
22:34, 28 дек 2013

x
> Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного
> варианта (первые две картинки)?
> Выведи его нормально.
> _d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
> _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Report | Блендинг по альфа-маске в Direct3D

Вывел оба варианта так как ты сказал. А тут может иметь значение вот эта штука, которая прописана у меня в инициализации?

_d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);

Честно говоря я её скопипастил из туториала по 2D движку на квадах без D3DX'а и приладился с ней жить.
Там, где мне нужно выводить свет (наложение Overlay) я рисую как раз вот так:

_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
Overlay | Блендинг по альфа-маске в Direct3D

Я что-то делаю не так?

x
> Там есть ещё проблема, альфа-тест нужно включать.
Проверил, работает без него.

_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
#26
22:36, 28 дек 2013

x
> Твои блики на данной картинке прибавляются к фону. Обычная прозрачность работает не так.
Черт, действительно, я в эйфории не заметил. :(

#27
22:51, 28 дек 2013

Kozinaka
Ну судя по картинкам 2 и 3

Изображение

Изображение

Премультиплай похож на правду.
Ну собственно твоя картинка 5, "Тестовое наложение блика по маске" верна, но там есть проблема.
Суть в том, что те пиксели которые вроде бы и отсекаются маской, все равно затемняют фон.
Чтобы проблемы не было видно, включи альфатест - тогда полностью прозрачные пиксели накладываемого спрайта отсекутся и действительно не будут косвенно затемнять фон.

#28
23:10, 28 дек 2013

x
> Чтобы проблемы не было видно, включи альфатест - тогда полностью прозрачные
> пиксели накладываемого спрайта отсекутся и действительно не будут косвенно
> затемнять фон.
Вот так включаю:

_d3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
_d3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x00000000); 
_d3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

Если включать только для вывода спрайта бликов, то ничего не меняется.
Если включить для вывода всех спрайтов, то срезает полностью прозрачные области в маске:
WrongAlphaTest | Блендинг по альфа-маске в Direct3D

Альфатест, получается, проверяет исходную альфу в спрайте, а не результат блендинга.

#29
23:28, 28 дек 2013

>Альфатест, получается, проверяет исходную альфу в спрайте, а не результат блендинга.
Чёрт, да. Об этом не подумал.

Хотя ты сделай нормальный порог, не 00, а там 0x00000020 какие-нибудь. Чтобы точно убедиться.

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорум2D графика и изометрия

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