Локални отражения на SSLR екранно пространство в AAA игри
Здравей приятел! Този път отново ще повдигна въпроса за графиките вAAA-игрите. Вече разгледах техникатаHDRR(да не се бърка с HDRI) тук и говорих малко за корекцията на цветовете. Днес ще обясня какво представляваSSLR(известен също като SSPR, SSR):Местни отражения на екранното пространство. На кого му пука - под котката.
Въведение в отложеното изобразяване
Като начало ще представя такова понятие катоОтложено изобразяване(да не се бърка сОтложено засенчване, тъй като последното се отнася до осветлението). Какво представляваотложеното изобразяване? Факт е, че всички ефекти (като осветление, глобално засенчване, отражения,DOF) могат да бъдат отделени от геометрията и тези ефекти могат да бъдат реализирани като специален вид последваща обработка. Например, какво ни трябва, за да приложимDOF(Depth Of Field, размазване на големи разстояния) към нашата сцена? Имате самата сцена (Цветна карта) и разполагайте с информация за позицията на тексел (с други думи, колко далеч е даден пиксел от камерата). Освен това - всичко е просто. ПриложетеBlurкъмColor Map, където радиусът на замъгляване ще зависи от дълбочината на пиксела (отDepth Map). И ако погледнете резултата - колкото по-далеч е обектът, толкова повече ще бъде размазан. И така, какво прави техникатаОтложено изобразяване? Той изгражда така нареченияGBuffer, който обикновено включва три текстури (RenderTarget):
- Цветна карта(информация за дифузен компонент или само цвят на пиксел)
- Нормална карта(информация за нормата на „пиксела“)
- Карта на дълбочината(информация за позицията на „пиксела“, тук съхраняваме само дълбочината)
В случай наColor map,Normal mapвсичко изглежда ясно, това са обикновениSurface.Colorтекстури: може би, с изключение на това, че нормалният вектор може да лежи в[-1, 1](използвайки просто опаковане на вектора във формат[0, 1]).
Но ситуацията сDepth mapстава неразбираема. КакDepth mapсъхранява информация за позицията на пиксел и дори едно число? По силно опростен начин трансформацията на примитив:
Дава ни екранни координати:
И малко информация за това колко „далеч“ е пикселът от камерата:
Въз основа на товаUVне ни е необходим, защото когато рисувате обикновена четворка на цял екран, това вече е известно. Следователно си струва да съхранявате в картата на дълбочината не позицията на пиксела, а само дълбочината.
В бъдеще ще можем да реконструираме позицията на пиксела по много прост начин:
Позволете ми да ви напомня, че за изграждането наGBufferви е необходима такава техника катоMRT(Multiple Render Targets), която рисува модела в няколкоRender Targetнаведнъж (и всекиRTсъдържа различна информация). Едно от правилата наMRTе, че всички размери наRender Targetтрябва да бъдатедни и същи. В случай наColor Map,Normal Map—Surface.Color: 32-bitRT, където всекиARGBканал има 8 бита, т.е. 256 степени от 0 до 1.
Благодарение на този подход можем да приложим сложни ефекти към всяка геометрия, като най-популярния ефект на Space Screen: SSAO (Space Screen Ambient Occlusion). Този алгоритъм анализира дълбочината и нормалните буфери, като отчита нивото на засенчване. Няма да описвам целия алгоритъм, той вече е описан на Хабре, само ще кажа, че задачата на алгоритъма се свежда до проследяване на карта на дълбочината: имаме набор от произволни вектори, насочени от разглеждания „пиксел“ и трябва да намерим броя на пресичанията с геометрията.
Примерефект (вляво без SSAO, вдясно със SSAO):
Освен товаОтложеното засенчванее ефект наПространствен екран. Тези. за всяка светлина на екрана (без никакви оптимизации) рисуваме четириъгълник в режимAdditiveв така нареченатаRenderTarget:Light Map. И като знаем световната позиция на „пиксела“, неговата норма, позицията на източника на светлина, можем да изчислим осветеността на този пиксел.
ПримерОтложено засенчване(осветяването се отлага след рендиране на геометрията):
Плюсове и минуси на ефектите на Space Screen
Най-важното предимство на ефектитеSpace Screenе независимостта на сложността на ефекта от геометрията.
Основният недостатъке локалността на всички ефекти. Факт е, че постоянно ще срещамеИзгубена информация, в много случаи това зависи много от прегледа, тъй катоSSEзависи от съседни дълбочини на тексел, които могат да бъдат генерирани от всякаква геометрия.
Е, струва си да се отбележи, чеЕфектите на екранното пространствосе изпълняват изцяло на графичния процесор и са с последваща обработка.
Най-накрая SSLR
След цялата теория стигаме до такъв ефект катоЛокални отражения в екранното пространство: локални отражения в екранното пространство.
Нека започнем с перспективна проекция:
Хоризонталните и вертикалните ъгли на видимост се задават отFOV(обикновено 45 градуса, аз предпочитам 60 градуса), те са различни във виртуалната камера, т.к.Aspect Ratio(съотношение на страните) също се взема предвид.
Прожекционният прозорец (където работим с данни отUV пространството) е това, което виждаме, върху което проектираме нашата сцена. Предната и задната равнина на изрязване са съответноБлизка равнина, Далечна равнина, те също са зададени в проекцията като параметри.В случай наОтложено изобразяване, струва си да направите стойносттаFar Planeтвърде голяма, т.к. Точността наDepth Bufferще падне много: всичко зависи от сцената.
Сега, знаейки проекционната матрица и позицията на прожекционния прозорец (както и дълбочината) за всеки пиксел, ние изчисляваме неговата позиция, както следва:
След като трябва да намерим вектора на изглед за този пиксел:
CameraPosition е позицията на камерата. И намерете отражението на този вектор от нормалата в текущия пиксел:
Освен това задачата се свежда до проследяване на картата на дълбочината. Тези. трябва да намерим пресечната точка на отразения вектор с някаква геометрия. Ясно е, че всяко проследяване се извършва чрез итерации. И ние сме много ограничени в тях. защото всяко извличане отДълбочинна картаструва време. В моята версия вземаме някакво първоначално приближениеLи динамично го променяме въз основа на разстоянието между нашия тексел и позицията, която „възстановихме“:
Спомагателни функции, превеждащи световната точка в екранното пространство:
След приключване на итерациите имаме позицията на „пресечна точка с огледална геометрия“. И нашата nuv стойност ще бъде проекцията на това пресичане върху екрана, т.е.nuv.xyеUVкоординатите в нашето екранно пространство, аnuv.zе извлечената дълбочина(т.е. abs(GetDepth(nuv.xy)-nuv.z) трябва да е много малък).
В края на итерациитеLще покаже разстоянието на отразения пиксел. Последната стъпка всъщност е добавянето на отражението къмЦветната карта:
След като компилираме шейдъра (отражение), получаваме следната картина (цветна карта от GBuffer + SSLR шейдър резултат):
Не е дебел. И тук си струва да припомним още веднъж, че ефектитеSpace-Screenса солидниInformation Lost(примерите са подчертани в червени кутии).
Факт е, че ако векторът на отражение надхвърлиSpace-Screen- информацията заColor-картата става недостъпна и виждамеClampingна нашияUV.
За да коригирате частично този проблем, можете да въведете допълнителен коефициент, който ще отразява "обхвата" на отражението. И по-нататък върху този коефициент ще засенчим отражението, проблемът е частично решен:
Резултат, отражение, умножено погрешка(опит за премахване на SSLR артефакта - загубена информация):
Вече по-добре, но забелязваме друг проблем, какво се случва, ако векторът се отрази в посоката на камерата?ЗатяганеиUVобаче няма да възникнат въпреки уместността на UV (x>0, y>0, x
Този проблем също може да бъде частично решен, ако по някакъв начин се ограничат ъглите на допустимите отражения. Чип с ъгли отефекта на Френеле идеален за това:
Леко променяме формулата:
Стойности на Fresnel, като се вземе предвид нормалното картографиране (стойности на променливата Fresnel за алгоритъма SSLR):
Областите, които се отразяват на „камерата“, ще бъдат черни и ние не ги вземаме под внимание (вместо това можете да направите избледняване в кубична текстура).
Отражение, умножено погрешкаифренел(опит за премахване на повечето SSLR артефакти):
Между другото, стойносттаFresnelтрябва да бъде ограничена от някакъв параметър, защото поради "грубостта" на нормалите, стойността ще бъде с порядък по-голям от единица (или друг ограничител на числото).
И последният етап от днешната статия е замъгляването на отраженията, т.к. перфектно отражение само в огледалото. Степента на замъгляване може да се разглежда като1-грешка(колкото по-далече е отразеният пиксел, толкова по-замъглено). Ще бъде любезнотегло на размазване и го съхранявайте в алфа канала на отражениятаRT.
Резултат (крайно изображение с премахнати артефакти и замъглени отражения):
Заключение
Също така си струва да добавите малко информация за отразяващата способност: колко ясно е отражението, доколко повърхността изобщо може да отразява, в онези места, където SSLR не работи - добавете статично отражение на текстурата на куба.
Разбира се, ефектитеSpace-Screenне са честни и разработчиците се опитват да скрият артефактите, но сега в реално време това (със сложна геометрия) е невъзможно да се направи. И без такива ефекти играта започва да изглежда някак грешно. Описах общатаSSLRтехника: дадох основните точки от шейдъра. За съжаление не мога да прикача кода, защото Има твърде много зависимости в проекта.