Запечёный GI на webGL.
Техническая часть.
Код не покажу, потому что это НДА и просто душно. Алгоритм расскажу, потому что это можно и круто. Всё это происходило давно, и все полезные на тот момент ссылки да ресурсы сейчас утеряны и/или неактуальны. Да и хуй с ними.
Делали какую-то пострелушку на браузерном движке Playcanvas. По какой-то причине нам захотелось добавить туда global illumination, который предварительно красиво запечь где-нибудь там в гудини например. Чтоб персонаж бегал по левелу, и угарно освещался этим левелом. Но лайтпроб-то в плейканвасе нету. Значит придётся их своими руками сделать. На мне повисла работа по движку, на другом серьёзном пацане работа по гудини. Идея запекания проста: разбить пространство на грид точек, в каждой точке посчитать освещённость (цвет, интенсивность опционально), все эти значения упаковать в жсон и отдать мне. Идея лайтпроб тоже проста: засунуть этот жсон в шейдер, и шейдером разобраться с какого раена конкретная точка на геометрии, которую сейчас надо осветить, кто её ближайшие соседи из запечённого грида, и проинтерполироваться между этими соседями. Реализация оказалась тоже проста — всё как задумали, так и сделали. По части запекания в гудиче я хз какие проблемы возникали, это были не мои проблемы. У меня же возникла беда с суванием жсона в шейдер, ибо webGL того времени не поддерживал никаких буферов, и никаким удобным образом массив кастомных данных в GPU не передать. Но есть неудобный способ, который я уже применял в декалях — закодировать всю эту парашу в текстуру, и отправлять в видеокарту текстуру. Благо наши так называемые кастомные данные — это RGB, так что и кодировать даже ничего не пришлось, взял цвет точки, положил в цвет текселя, хуль тут сложного. Ну и вот, теперь у меня есть текстура, в каждом пикселе которой находится значение освещённости в какой-нибудь точке сцены. Эту текстуру я могу сувать в шейдер. Шейдер написал без приключений — там просто определение соседей да интерполяция между ними, ничего интересного. А потом снова нюанс: этот фейк-джиай должен быть встроен во все материалы сцены. Чтобы художники там понастраивали материальчики, игру включили, а мой GI опа и работает сам собой. И такую возможность встраивания своего кода в код материала плэйканвас предоставляет. Молодец какой. Там это называется shader chunks. Суть в том, что шейдеры компилятся при запуске игры, а не в едиторе. В едиторе же они хранятся текстом, просто открытым голым кодом валяются, а значит промеж этого заводского кода можно сувать свой кастомный код. И при запуске компилиться будет уже заводской шейдер со встроенными кусками моего. Я свой шейдер и положил во все материалы в чанк люминанса. А потом чтобы художники могли новые материалы добавлять, и меня не дёргать мол включи ну включи джиай, я бахнул скрипт, который при запуске ещё до компиляции шейдеров все материалы собирает, и суёт в них мой шейдер.
Гуманитарная часть.
Давным-давно я щупал движок юниджайн, кажется это был ещё 2014. Там я увидел лайтпробы и охуел как вкопанный. Это казалось обоссаным чудом, что глобал иллюминейшен возможен в риалтайме хоть в каком-то виде. Я тогда думал, что это какие-то надмозги придумали и даже не пытался там что-то изучить или поприкидывать, как это могли сделать; просто подумал «не для моих мозгов», пустил дегенеративную слюнку и забил хуйца. И вот спустя шесть лет мне поставили задачку бахнуть этот иллюминейшен в браузере. И мне не понадобилось даже ничего гуглить, идея как это сделать пришла сразу же, я сразу эту идею реализовал, и всё прошло гладко, легко и быстро. На протяжении всего дня разработки я не воспользовался гуглом ни разу. Задачка казалась пугающей издалека, но вблизи на практике выяснилось, что а разговоров-то было.