x
Супер! SRC.R'G'B' * DEST.A, это и получается SRC.RGB * SRC.A * DEST.A, перемножение альфы, которое требуется. Прости, что туплю, для меня ново это всё.
MrShoor
> Ну глядя на видео - похоже тебе нужно стекло строго внуртри дырок? Без нахлеста же?
Ага, стекло строго внутри дырок, но это на тестовых тайлах на видео дырки ровные и симметричные, а в реальном тайлсете (как на картинке в нуль-посте) края стекла могут быть другими, с трещинами, например. Нахлёста, конечно, нет. Тайлы дырок просто выводятся рядом друг с другом, на каждый сверху хочется наложить по его индивидуальной маске индивидуально подогнанный фрагмент спрайта блика. Так, чтобы казалось, что блик цельный для всего стекла и двигался в зависимости от положения камеры.
Твоя концепция ещё не развалилась? Я зацепился за слово "запекать", а сути приёма просто не понял, т.к. не слишком силён в этой кухне. Я раньше D3DX использовал без каких-либо сложных приёмов, просто спрайты с альфой накладывал друг на друга и не парился. А сейчас пытаюсь поднять игру на более серьёзный уровень, перешел на чистый Direct3D и пытаюсь сориентироваться чего я тут вообще могу.
Прошлая публичная версия полтора года назад была: http://www.gamer.ru/nesyt/simulyator-plotoyadnogo-chervya
Но сейчас уже всё по-другому, думаю через месяцок-другой смогу открыть тему в "Проектах".
А про релиз, честно говоря, боюсь думать. Надеюсь летом хоть что-нибудь опубликовать.
Поход с блендингом сработает только если у тебя в Dest реально сохраняется альфа.
Так если без нахлеста - то я не понял почему нельзя тупо пордяком отрисовки подсовывать блики под накладку?
Буду оперировать картинками из 0 поста.
1. Рисуем травку с букашками
2. Рисуем стекло
3. Рисуем накладку на фон
Почему нельзя так сделать то?
MrShoor
> почему нельзя тупо пордяком отрисовки подсовывать блики под накладку?
Я думал о такой теме, но мешает этому декор под стеклом. Посмотри на картинку в нуль-посте - у окошка под стеклом есть провода, железки и прочее, что должно перекрываться и стеклом и бликами на стекле.
Можно применить предложенный тобой подход, если разложить окошко на два слоя - нижний декор и накладываемые края со стеклом. Пока считаю это аварийным вариантом, т.к. процесс разрезания на части довольно морочен. Надеюсь получится реализовать всё с маской - это более универсальный подход, который я смогу активно использовать не только на окошках, но на любом объекте в игре, который я захочу сделать бликующим.
> Я думал о такой теме, но мешает этому декор под стеклом. Посмотри на картинку в нуль-посте - у окошка под стеклом есть провода, железки и прочее, что должно перекрываться и стеклом и бликами на стекле.
Значит все таки нахлест есть. Ну попробуй с альфой, если не получится - будем думать. Можно стенсилом конечно почикать это, правда пропадет антиалиясинг на краях круга... Проще всего конечно мультитекстурированием решить проблему.
Что-то пока не выходит. :(
Рисую спрайт бликов с premultiplied alpha вот так:
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA); _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
На выходе получаю всё как надо там, где у маски alpha=255, но чем прозрачнее маска, тем темнее результат на выходе (а должен быть прозрачнее). Вот иллюстрация:
Альфа от маски точно прописывается в DEST, т.к. если выводить спрайт блика вот так:
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA); _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
То, видно, что по альфе из DEST всё хорошо режется. Ну и, конечно, при таком выводе ожидаемо игнорируется альфа из спрайта бликов.
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. На разных картинках блик по-разному внутри себя сдвинут, это не ошибка, просто скриншоты делал с разных положений камеры.
>Есть какие-нибудь идеи?
Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного варианта (первые две картинки)?
Выведи его нормально.
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Допустим в блике у тебя записана аргб:
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);
MrShoor
Метод тыка ок.
Kozinaka
Там есть ещё проблема, альфа-тест нужно включать.
x
> Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного
> варианта (первые две картинки)?
Ну, у в предумноженном варианте цветовые составляющие перемножились с альфой, там где альфа была меньше 1, там при прямом выводе цвета стали темнее.
MrShoor
> _d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
> _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
УРРРРА! ПОЛУЧИЛОСЬ!
x, MrShoor, спасибо вам огромное за помощь!
Kozinaka
>УРРРРА! ПОЛУЧИЛОСЬ!
На самом деле нет. Твои блики на данной картинке прибавляются к фону. Обычная прозрачность работает не так.
x
> Для начала, почему у тебя "исходный блик" отличается по виду от предумноженного
> варианта (первые две картинки)?
> Выведи его нормально.
> _d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
> _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Вывел оба варианта так как ты сказал. А тут может иметь значение вот эта штука, которая прописана у меня в инициализации?
_d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
Честно говоря я её скопипастил из туториала по 2D движку на квадах без D3DX'а и приладился с ней жить.
Там, где мне нужно выводить свет (наложение Overlay) я рисую как раз вот так:
_d3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); _d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
Я что-то делаю не так?
x
> Там есть ещё проблема, альфа-тест нужно включать.
Проверил, работает без него.
_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
x
> Твои блики на данной картинке прибавляются к фону. Обычная прозрачность работает не так.
Черт, действительно, я в эйфории не заметил. :(
Kozinaka
Ну судя по картинкам 2 и 3
Премультиплай похож на правду.
Ну собственно твоя картинка 5, "Тестовое наложение блика по маске" верна, но там есть проблема.
Суть в том, что те пиксели которые вроде бы и отсекаются маской, все равно затемняют фон.
Чтобы проблемы не было видно, включи альфатест - тогда полностью прозрачные пиксели накладываемого спрайта отсекутся и действительно не будут косвенно затемнять фон.
x
> Чтобы проблемы не было видно, включи альфатест - тогда полностью прозрачные
> пиксели накладываемого спрайта отсекутся и действительно не будут косвенно
> затемнять фон.
Вот так включаю:
_d3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); _d3dDevice->SetRenderState(D3DRS_ALPHAREF, 0x00000000); _d3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
Если включать только для вывода спрайта бликов, то ничего не меняется.
Если включить для вывода всех спрайтов, то срезает полностью прозрачные области в маске:
Альфатест, получается, проверяет исходную альфу в спрайте, а не результат блендинга.
>Альфатест, получается, проверяет исходную альфу в спрайте, а не результат блендинга.
Чёрт, да. Об этом не подумал.
Хотя ты сделай нормальный порог, не 00, а там 0x00000020 какие-нибудь. Чтобы точно убедиться.
Тема в архиве.