Как создать эффект бликов на линзах — подробный туториал
Для всех, кто хочет повторить впечатляющие блики из Cyberpunk 2077.
Блики на линзах — это фотографический артефакт, который возникает при взаимодействии объектива и света. Этот эффект также встречается в играх — разработчики сознательно добавляют его по нескольким причинам:
- он увеличивает яркость и динамический диапазон изображения;
- блики усиливают погружение, так как позволяют ощутить «физичность» камеры;
- эффект может играть важную стилистическую или драматическую роль. Также его можно использовать в качестве игровой механики: к примеру, блики могут ослеплять игрока.
Разработчик Джон Чепмен в 2013 году опубликовал в своём блоге подробный туториал, в котором рассказал, как реализовать эффект бликов в игре. Автор поделился нужным кодом, а также дал описание к каждому этапу создания бликов. Мы выбрали из текста главное.
Традиционно для создания бликов применяют спрайты, так как их легко настраивать, а также они выглядят достаточно реалистично. Но для их корректной работы нужно использовать occlusion-данные, что может усложнить задачу. Чепмен предложил иной подход, который не даёт таких же реалистичных результатов, но может частично заменить спрайты.
На первом этапе важно определить самые яркие пиксели на оригинальном изображении, чтобы на их основе сделать блики. Также нужно использовать даунсемплинг для оптимизации. Самый простой и гибкий способ — применить scale и bias.
Эффект можно настроить с помощью параметров scale и bias: результат сильно зависит от динамического диапазона, а также интенсивности бликов. Следите за тем, чтобы они получились не слишком яркими.
Блики на линзах обычно вращаются вокруг центра изображения. Чтобы имитировать эту особенность, можно просто перевернуть результат предыдущего этапа по горизонтали и вертикали:
Следующий шаг: создание «призраков» — повторяющихся бликов, которые появляются с противоположной стороны относительно центра изображения. Чтобы сделать их, нужно взять вектор, идущий от пикселя к центру экрана, а затем получить несколько сэмплов вдоль этого вектора.
Эффект можно улучшить, если поставить условие, что «призраки» появляются только от ярких источников света в центре изображения. Чтобы добиться этого, нужно добавить сэмплам вес, который уменьшается по мере удаления от центра экрана:
Функция веса достаточно проста — она выглядит как линейное убывание. Вес используется только внутри области сэмплов. Это нужно, чтобы «призраки» создавались только от тех источников света, которые находятся в центре изображения.
Окрашивание применяется в последнюю очередь, чтобы повлиять на финальный цвет «призраков».
Следующий шаг — создание эффекта гало. Если взять вектор к центру изображения, но зафиксировать длину вектора, то получится нужный эффект — исходное изображение будет радиально искривлено.
Чтобы создать эффект гало, нужно определить область веса, как в случае с «призраками». Только на этот раз область должна быть не в центре изображения, а по краям. Радиус получившегося овального кольца контролируется при помощи uHaloWidth.
Ещё одна часть эффекта — хроматические искажения. В реальности у некоторых бликов заметны хроматические искажения, которые появляются из-за того, что волны света разной длины преломляются по-разному. Эту особенность можно смоделировать, если создать функцию, которая разделяет красный, зелёный и синий каналы, а потом немного смещает каждый из них вдоль вектора сэмплинга.
Чепмен использовал следующие параметры направления и искажения:
Сейчас блики получились слишком чёткими. Чтобы исправить это, нужно добавить эффект blur. Чепмен не стал подробно рассказывать об этом, но указал ссылку на туториал.
Теперь нужно смешать полученный эффект с исходным изображением. Но нужно учитывать две вещи. Во-первых, эффекты motion blur или depth of field необходимо добавить до объединения бликов с исходным изображением. Это значит, что постобработка не будет накладываться на блики. Во-вторых, если вы собираетесь использовать tonemapping, то добавьте блики перед объединением, так как этот эффект должен распространяться и на них.
Чтобы сделать эффект более реалистичным, можно добавить текстуру грязи.
Если у текстуры грязи низкий контраст, то блики будут сильно выделяться. Если увеличить его, то блики станут более приглушёнными.
Также можно добавить текстуру starburst. Она не очень хорошо выглядит в качестве статичной текстуры, но это можно исправить — нужно поместить матрицу преобразования в шейдер: это позволит вращать и деформировать её для получения нужного динамического эффекта.
Матрица преобразования uLensStarMatrix основана на значении положения камеры:
Значение camrot можно получить и иным способом — оно должно постоянно меняться, когда вращается камера. Вот как выглядит сама матрица:
Матрицы scale и bias нужны для смещения начала координат текстуры, чтобы можно было вращать starburst вокруг центра изображения.
В результате получился сравнительно простой способ создания эффектов бликов от линз, который строится на основе постобработки. Результат нельзя назвать полностью фотореалистичным, но при должной настройке он может выглядеть отлично.