- Как настроить static point scale
- Unity ID
- Пока смерть не разлучит нас или всё о static в C++
- Что такое ic?
- Где используется?
- Статические переменные внутри функции
- Позиционирование и масштабирование в CSS с transform Translate и Scale. Как вычислить позицию элемента?
- Работа с освещением в Unity — теория и практика
- Теория освещения
- Отражённый свет
- Ambient Occlusion
- Текстурные атласы
- Работа с Unity
- Общая информация
- Параметры источников света
- Настройка освещения сцены
- Раздел — Object
- Раздел — Scene
- Вкладка — Baked GI
- Вкладка — General GI
- Вкладка — Fog
- Раздел — Lightmaps
- Light Probes
- Заключение
Как настроить static point scale
Unity ID
A Unity ID allows you to buy and/or be to Unity products and services, shop in the Asset Store and participate in the Unity .
So I had a problem, and I solved it, and because I saw lots of questions it, but without a solution, here is how I solved it:
Unity has Transform.RotateAround
Rotates the transform axis passing through point in world coordinates by angle degrees.
But it doesn’t have ScaleAround
In order to scale around a point in the world, you’ll need this formula:
GameObject Local Position
New pivot position(relative to object’s parent)
Old scale Vector3(2,2,2)
New scale Vector3(5,5,5)
Find Object position relative to pivot(It’s similar to put the game object as a child of a pivot object, and then get it’s localPosition):
Relative Scale(we need to check how much did the object scaled):
RS=New Scale / Old Scale
Vector3.Scale(Vector3(2.5,2.5,2.5), Vector3(5,3,1)) + Vector3(4,5,6)
(Relative Scale * Object Position Relative to Pivot) + Pivot Position
Afroman and amonitzer like this.
I don’t understand where do you get:
Old scale Vector3(2,2,2)
New scale Vector3(5,5,5)
Where do you get those values from and why do you have two scale values?
The rest is crystal clear.
Last edited: Jul 3, 2014
I’ve translated De-Panther’s pseudocode into working code. Enjoy:
var targetGO : GameObject;
var pivotGO : Transform;
var A : Vector3 = targetGO.transform.position;
var B : Vector3 = pivotGO.transform.position;
var RS : float = 0.2; // relataive scale factor
var startScale = targetGO.transform.localScale;
var endScale = targetGO.transform.localScale *RS;
var C : Vector3 = A-B; // diff from object pivot to desired pivot/origin
// calc final position post-scale
var FP : Vector3 = (C*RS)+B;
// finally, actually perform the scale/translation
Joined: Nov 15, 2013 Posts: 9
I’ve created ic method to scale target around the pivot:
public ic void ScaleAround(Transform target, Transform pivot, Vector3 scale) <
Transform pivotParent = pivot.parent;
Vector3 pivotPos = pivot.position;
target.position += pivotPos — pivot.position;
So trul’s code with parenting wasn’t quite what I personally was looking for and I couldn’t get it to work, but gregroberts’s example code also didn’t work for me out of the box, so I eventually made this:
I’ve translated gregroberts’s mostly-working (I’m assuming Java) code translation of De-Panther’s pseudocode into fully ing and tested C#:
public void ScaleAround(GameObject target, Vector3 pivot, Vector3 newScale)
Vector3 A = target.transform.localPosition;
Vector3 B = pivot;
Vector3 C = A — B; // diff from object pivot to desired pivot/origin
float RS = newScale.x / target.transform.localScale.x; // relative scale factor
// calc final position post-scale
Vector3 FP = B + C * RS;
// finally, actually perform the scale/translation
ScaleAround(targetGameObject, scaleCenterPivot, desiredFinalScale);
Alternatively, if you would rather use a Transform / GameObject’s position as the pivot, you can do:
ScaleAround(targetGameObject, pivotGameObject.transform.position, desiredFinalScale);
Just remember: It is extremely important that the pivot point be in the target’s PARENT’S space. So if your target object has no parent, your pivot is in world space. If your target is a child of SomeGameObject, you pivot point must be in SomeGameObject’s space. This can be accomplished with
if your pivot is in world space.
Hope this helps someone who needed it as much as I did, thanks to everyone who contributed here, and happy coding!
@KyleBlumreisinger , I’m happy that it helped someone after so many years
I think that the «target» type on ScaleAround should be Transform.
And maybe we can add a bool that ask if pivot is in parent space or world space.
Also, now that I think it, it works only if the scaling was unified.
So iguess it shold be:
Vector3 RS= new Vector3(newScale.x / target.transform.localScale.x, newScale.y / target.transform.localScale.y, newScale.z / target.transform.localScale.z);
Vector3 FP = B + C.Scale(RS);
But I’ll have to test it.
This was excellent. It’s easy to forget that final positions need to also be handled as we’ve come so much to rely on parenting…
Last edited: Sep 3, 2018
I know it’s an older post but just for completeness and to help others who might come across this.
So here are some versions of this method with some write-up on how they work.
I took the liberty to add @De-Panther s suggestions.
/// Scales the target around an arbitrary point by scaleFactor.
/// This is relative scaling, meaning using scale Factor of Vector3.one
/// will not change anything and new Vector3(0.5f,0.5f,0.5f) will reduce
/// the object size by half.
/// The pivot is assumed to be the position in the space of the target.
/// Scaling is applied to localScale of target.
The object to scale.
The point to scale around in space of target.
The factor with which the current localScale of the target will be multiplied with.
public ic void ScaleAroundRelative(GameObject target, Vector3 pivot, Vector3 scaleFactor)
var pivotDelta = target.transform.localPosition — pivot;
target.transform.localPosition = pivot + pivotDelta;
var finalScale = target.transform.localScale;
/// Scales the target around an arbitrary pivot.
/// This is absolute scaling, meaning using for example a scale factor of
/// Vector3.one will set the localScale of target to x=1, y=1 and z=1.
/// The pivot is assumed to be the position in the space of the target.
/// Scaling is applied to localScale of target.
The object to scale.
The point to scale around in the space of target.
The new localScale the target object will have after scaling.
public ic void ScaleAround(GameObject target, Vector3 pivot, Vector3 newScale)
Vector3 pivotDelta = target.transform.localPosition — pivot; // diff from object pivot to desired pivot/origin
Vector3 scaleFactor = new Vector3(
target.transform.localPosition = pivot + pivotDelta;
I’d argue that «ScaleAroundRelative()» is the way most people would assume the ScaleAround() methods from above work. Unitys own RotateAround() also works relative (rotate by) instead of absolute (rotate to angle).
Last edited: Jul 23, 2020
Пока смерть не разлучит нас или всё о static в C++
Всем привет. На одном из код-ревью я столкнулся с мыслью, что многие, а чего скрывать и я сам, не то чтобы хорошо понимаем когда нужно использовать ключевое слова ic. В данной статье я хотел бы поделиться своими знаниями и информацией по поводу ключевого слова ic. Статья будет полезна как начинающим программистам, так и людям, работающим с языком С++. Для понимания статьи у вас должны быть знания о процессе сборки проектов и владение языком С/С++ на базовом уровне. Кстати, ic используется не только в С++, но и в С. В этой статье я буду говорить о С++, но имейте в виду, что всё то, что не связано с объектами и классами, в основном применимо и к языку С.
Что такое ic?
ic — это ключевое слово в C++, используемое для придания элементу особых характеристик. Для статических элементов выделение памяти происходит только один раз и существуют эти элементы до завершения программы. Хранятся все эти элементы не в heap и не на stack, а в специальных сегментах памяти, которые называются .data и .bss (зависит от того инициализированы статические данные или нет). На картинке ниже показан типичный макет программной памяти.
Где используется?
Ниже приведена схема, как и где используется ic в программе.
А теперь я постараюсь детально описать все то, что изображено на схеме. Поехали!
Статические переменные внутри функции
Статические переменные при использовании внутри функции инициализируются только один раз, а затем они сохраняют свое значение. Эти статические переменные хранятся в статической области памяти (.data или .bss), а не в стеке, что позволяет хранить и использовать значение переменной на протяжении всей жизни программы. Давайте рассмотрим две почти одинаковые программы и их поведение. Отличие в них только в том, что одна использует статическую переменную, а вторая нет.
Этот текст должен быть читаемым на всех устройствах без увеличения страницы жестами. Открыл и прочитал.
Источник
Позиционирование и масштабирование в CSS с transform Translate и Scale. Как вычислить позицию элемента?
В общем уже битый час мучаюсь, но не могу понять следующее:
У меня имеется изображение (больше никаких блоков на странице нет, только одно изображения, ничего лишнего), скажем 400×400. Так вот, я перемещаю это изображение с помощью функции css3 translateX задаю, к примеру, 500px и изображение смещается на 500px вправо. Все работает так как и ожидается, но когда применяю масштабирование (scale) то translate ведет себя невообразимым образом, он двигает изображение меньше чем на 500px, если масштаб изображения уменьшается, а если увеличивается, то дальше чем на 500px.
Я слышал, что translate использует какую-то там субпиксельную интерполяцию, но так до конца и не понял.
В общем, каким образом, по какой формуле можно высчитать правильные пиксели? К примеру, если я уменьшил изображение со scale на 50% то как мне сдвинуть это изображение в правую сторону на 500px? По какой формуле? Куда копать? Ребята . )
- Вопрос задан более трёх лет назад
- 873 просмотра
Там есть нюанс с порядком объявления свойств. В вашем случае scale должен идти после translateX .
transform: translateX(500px) scale(1.5);
Если я не ошибаюсь, операторы в свойстве transform выполняются справа налево, причем некоторые из них влияют на те, что справа.
× transform: translateX(100px) scale(3); – сначала увеличили в три раза, потом переместили на 100px
× transform: scale(3) translateX(100px); – сначала переместили на 100 вправо, потом увеличили в 3 раза, но, так как здесь scale влияет на translateX, поэтому конечный translateX тоже увеличивается в 3 раза и будет равен 300px
Источник
Работа с освещением в Unity — теория и практика
В течение последних пары лет мне приходилось много работать с “лайтмаппингом” как по работе, так и на своём собственном инди-проекте. Когда у вашей команды мало производственных ресурсов и вы не можете выделить много времени на создание уникальной графики для игровых локаций, освещение становится одним из ключевых факторов, помогающих оживить и разнообразить картинку.
Теория освещения
Отражённый свет
Давайте определимся с терминологией. Освещение в компьютерной графике делится, условно говоря, на две категории:
- Direct Illumination. Прямое попадание лучей света на поверхность.
- Indirect Illumination. Лучи отражаются от поверхности, рассеиваются и образуют мягкий заполняющий свет.
Есть много методов вычисления отражённого освещения, два самых известных — это Global Illumination (GI) и Final Gather (FG). Их можно использовать по отдельности, но вместе они выдают особенно хороший результат. Однако за всё приходится платить: рендер, то есть процесс вычисления сложного освещения и последующей его визуализации, займёт уйму времени.
Global Illumination (GI) представляет из себя наиболее “честный” способ симуляции отражённого света. Из источника света вылетают фотоны — частички, несущие информацию о цвете и яркости света. Ударяясь о какую-либо поверхность, они освещают её, но теряют часть энергии, вследствие чего их цвет и яркость изменяются. Затем фотоны отскакивают и ударяются о следующую поверхность, повторно теряя часть энергии. Так происходит несколько раз в зависимости от настроек рендерера.
Final Gather (FG) раскидывает по сцене точки, — final gather points, — из которых в разные стороны вылетают лучи. После столкновения с какой-либо поверхностью, лучи возвращают в родительскую точку информацию о цвете и его яркости. Представьте себе такую картину: вечер, солнце почти зашло за горизонт; становится темно, но небольшая часть комнаты ещё залита оранжевым закатным светом. Находящаяся на полу final gather point отправляет в разные стороны несколько лучей, некоторые из них дотягиваются до освещённой части комнаты и с этой информацией возвращаются в исходную точку, тем самым слегка освещая пол «отражённым» оранжевым светом. Это не такой “честный” способ, как GI, но он производит хороший результат, и им часто пользуются, чтобы заполнять сцены красивым мягким освещением.
Для следующей картинки я выкрутил параметры отражённого света до безумных значений, таким образом вы можете наглядно увидеть, как частички света отскакивают от объектов.
Ambient Occlusion
Кроме отражённого света, нам интересен так называемый Ambient Occlusion (AO). Это эффект затенения в углах, трещинах, узких проёмах. Представьте, что луч света залетает в угол комнаты, он несколько раз отражается от обеих стен, постепенно затухая. Чем дальше в угол, тем меньше света туда доходит.
Как правило, Ambient Occlusion используется, чтобы художественно подчеркнуть эффект затенения, — в реальности лучи света не теряют энергию столь быстро, чтобы в углах комнаты сгущалась такая же тьма, как показывают нам в играх. Если вы рендерите физически корректное освещение, ваш движок сам высчитывает скорость потери энергии лучом света, и вам не нужно отдельно рендерить карту (текстуру) Ambient Occlusion. Но вы можете это сделать, если потребуется для реализации художественного замысла.
Текстурные атласы
Следующим термином, который вам следует следует знать, является текстурный атлас. Грубо говоря, это одна большая текстура, в которой содержатся несколько маленьких текстурок. Чаще всего текстурные атласы создаются для экономии вычислительных ресурсов. Приведу крайне упрощённый пример, — спецы, спрячьте факелы и вилы! Пусть у вас в игре есть таверна, в которой 20 деревянных предметов (столы, стулья, ложки. ), у каждого своя текстура. В итоге CPU будет 20 раз обращаться к GPU, требуя отрендерить каждый объект по отдельности. Если мы назначим всем деревянным объектам один материал, обращающийся к одному текстурному атласу, в который зашиты все 20 текстур, то GPU сможет отрендерить 20 объектов за один вызов (он же — draw call, в конце статьи предоставлю интересные ссылки по этой теме).
В случае с “лайтмаппингом”, для каждого объекта создаётся дополнительная маленькая текстурка, в которой “запекается” информация об освещении. Затем много-много маленьких текстурок разных объектов размещаются в крупных текстурных атласах. Как и в случае с деревянной мебелью, мы также получаем прирост производительности.
Работа с Unity
Общая информация
Но вернёмся к “лайтмаппингу” в самом Unity. Прежде всего запаситесь терпением и, по возможности, мощным компьютером. Процесс рендера имеет свойство полностью занимать процессор и оперативную память, поэтому я включаю его перед тем, как ухожу на работу или иду спать. Таким образом, я возвращаюсь к компьютеру как раз в тот момент, когда рендер уже завершён.
Забегая вперёд, предупрежу, что Unity кэширует промежуточные результаты вычислений освещения. Если вы увидите, что на системном диске у вас пропало 10 гигабайт места — это оно. Чтобы настроить кэш надо зайти в: Edit — Preferences — GI Cache. Здесь вы можете указать, куда он сохраняется и его максимальный размер. Можно убрать компрессию, “весить” будет больше, но работать пошустрее. Тут же вы можете почистить кэш, но имейте ввиду, что если у вас открыта сцена с готовым “лайтмапом”, то он тоже будет удалён, будьте внимательны.
В Unity доступно 5 типов источников света:
- Directional Light. Самый простой, имитирует солнечный свет. Представляет из себя бесконечное множество параллельных друг другу лучей.
- Point Light. Точечный источник света, то есть лучи расходятся во все стороны из одной точки. Хорошим примером такого источника света будет обычная лампочка.
- Area Light. Источник света, имеющий площадь. Представьте себе прямоугольную панель, из которой исходит свет, это и будет area light. Такие источники света чаще всего используются в офисах, торговых центрах и других нежилых помещениях, где надо освещать большие пространства.
- Ambient Light. Заполняющий свет, не имеющий источника. Примеры использования: осветить слишком тёмные тени; добавить атмосферности подземелью, заполнив его едва заметным светом биолюминисцентных растений.
- Light Probes. Особый источник света, влияющий исключительно на динамические объекты. Технически это не источник света, но для простоты назовём его так.
В Unity все объекты делятся на динамические (dynamic) и статические (static). Статическими объектами называются те, которые всегда стоят на месте и никуда не смещаются. Именно для них происходит “запечение” освещения. Динамические объекты — это те, которые наоборот находятся в движении. Сюда входят такие элементы сцены, как герой, монстр, колышущийся флаг, падающий с обрыва камень. Для этих объектов не подходит “лайтмаппинг”, они освещаются либо real-time источниками света, либо посредством light probes, о которых я дополнительно расскажу в конце статьи.
Параметры источников света
Хочу обратить внимание на насколько ключевых настроек источников света (доступные настройки различаются в зависимости от типа источника света):
- Baking. Позволяет выбрать метод обработки источника света. Для “лайтмаппинга” ставим в положение Baked.
- Color. Собственно, цвет источника света.
- Radius. Параметр Point Light’а, отвечающий за то, как далеко летят лучи света.
- Intensity. Просто яркость источника света.
- Bounce Intensity. Определяет яркость отражённых лучей, выпущенных из текущего источника света.
- Shadow Type. Определяет отображение теней. Советую использовать Soft Shadows, это даёт красивые тени ценой увеличенного времени рендера.
- Baked Shadow Angle. Доступно только для Soft Shadows. Представьте себе длинную тень. Чем дальше она уходит от объекта, отбрасывающего её, тем более размытой она становится. Если параметр выставлен на “0”, то тень практически не будет размываться. Если выставлен на больше, чем “0”, то появится размытие.
Настройка освещения сцены
Окно настроек освещения сцены вызывается через Window — Lighting, и состоит из трёх вкладок: Object, Scene, Lightmaps. Для запуска рендера освещения используется кнопка Build в самом низу окна. Там же есть галочка Auto, которая автоматически запускает рендер каждый раз, когда вы вносите изменения в сцену; используйте её, если у вас мощный компьютер. Ещё ниже находится информация о количестве и размере “лайтмапов”, появится по завершению процесса “лайтмаппинга”.
Раздел — Object
В Object отображаются настройки конкретного объекта. Если вы выделите элемент окружения на вашей сцене, то здесь увидите ряд настроек и параметров. При условии, что объект является статичным, будет стоять галочка на чекбоксе Lightmap Static. Чаще всего вы будете использовать здесь поле Scale in Lightmap. Как я говорил ранее, для каждого объекта освещение “запекается” в отдельную маленькую текстурку, которая потом размещается в крупном “лайтмап”-атласе. Параметром Scale in Lightmap вы можете регулировать, сколько места будет занимать эта текстурка. Разумеется, чем меньше места ей выделяется, тем хуже будет качество “запечённого” в неё освещения. По умолчанию здесь стоит “1”, но если вы знаете, что объект будет редко попадать в поле зрения или он расположен далеко на фоне, вы можете смело уменьшить этот параметр вплоть до 0.1 или даже меньше.
Раздел — Scene
В Scene расположены ключевые настройки рендера освещения. Я рассказываю основы работы со светом, а также делюсь опытом “лайтмаппинга” конкретно под мобильные платформы, поэтому умышленно пропускаю такие вещи, как realtime GI или использование HDR-текстуры в качестве источника света.
В Ambient Source вы настраиваете заполняющий источник света Ambient Light, который я уже упоминал. Вам предлагается выбрать между небом-текстурой, небом из единственного цвета, а также созданным на основе цветового градиента небом. Я предпочитаю выбирать Gradient. Он позволяет настроить три цвета — купол неба, экватор и землю, что создаст для вашей сцены достаточно сложный и интересный заполняющий свет. Ambient Intensity указывает яркость этого света. В зависимости от художественного замысла, вы можете иметь даже очень светлую сцену, освещённую посредством одного Ambient Light.
Во вкладке Baked GI находятся основные настройки качества освещения, как прямого, так и отражённого, включая и GI, и FG.
Прежде чем углубимся в эти настройки, хочу дать один совет. Всегда имейте ввиду, что размещая на сцене источники света, настраивая тени и Ambient Light, после рендера “лайтмапа” вы получите совершенно иную картинку, только отдалённо напоминающую то, что вы делали. Поэтому я рекомендую работать итерациями: вы выставляете минимальное качество освещения, чтобы рендер происходил быстро, смотрите на результат рендера, после чего вносите правки и запускаете повторный рендер. Когда вы более-менее довольны результатом, можно повысить качество рендера и включить Final Gather. Это займёт длительное время, поэтому есть смысл включать такой рендер перед тем, как вы отходите от компьютера на сравнительно долгий отрезок времени.
Настройки во вкладке Baked GI оперируют такой единицей, как texel. Если говорить упрощённо, тексель — это пиксель, но не на экране, а в текстурном пространстве трёхмерной модели. Но не забивайте голову, — трудно сказать, как Unity оперирует текселями и как они зависят от масштаба объектов, поэтому просто-напросто двигайтесь эксперементальным путём. Например, для своей мобильной RPG я делаю финальный рандер с Baked Resolution выставленным в 25.
Тексель (сокращение от англ. Texture element) — минимальная единица текстуры трёхмерного объекта. Пиксель текстуры.
Проще всего объяснить значение термина «тексель» на примере трёхмерных игр. Если подойти вплотную к стене в какой-нибудь старой 3D-игре — (Wolfenstein или Duke Nukem), то можно наблюдать, как текстура стены распадается на однотонные квадраты, которые увеличиваются при приближении и собираются обратно в осмысленный рисунок при отдалении. Эти квадраты и называются текселями, и чем крупнее исходный рисунок текстуры, тем меньше становятся тексели. Для идеального отображения текстуры количество текселей должно совпадать с количеством пикселей на мониторе, но практически все движки разрешают зрителю приблизиться к стене ближе чем того разрешает детальность.
Ниже я расскажу про каждый параметр отдельно, но перед этим вам нужно знать ещё кое-что. Если вы запустите в Unity рендер освещения, то справа снизу будет написано, чем именно движок занят в текущий момент. В самом конце процесса рендера там будет написано Compositing.
Дело в том, что “лайтмап” генерируется послойно. Во время рендера создаются несколько отдельных текстур. Мне неизвестно, какие именно карты делает Unity, но среди них есть либо все, либо часть из списка: Diffuse (прямой свет), GI (Global Illumination), FG (Final Gather), AO (Ambient Occlusion) и другие. После этого движок берёт эти карты и сливает друг с другом. Например, в основе может лежать слой Diffuse, над ним кладётся слой FG в режиме смешивания Lighten (прямо как в Photoshop’е), а повыше кладётся слой AO в режиме Multiply… В итоге эти слои сливаются в одну картинку и на выходе получается финальный “лайтмап”.
Вкладка — Baked GI
Вкладка — General GI
Давайте пройдёмся по интересующим нас настройкам во вкладке General GI:
- Directional Mode. Весьма специфичный параметр, “запекающий” для каждого “лайтмапа” второй атлас. Обычный “лайтмап” представляет из себя простую текстуру, которая затем накладывается поверх ваших объектов, имитируя их освещённость. Второй же атлас, называемый Directional, содержит в себе информацию о направлении движения лучей света. Этот режим имеет смысл включать только если вы используете normal map’ы и работаете не над мобильной игрой. В противном случае рекомендуется брать Non Directional.
- Indirect Intensity. Можно сказать, что это яркость слоёв с непрямым светом, в частности FG. Ранее я уже рассказывал, что на самом деле “лайтмап” собирается из слоёв, накладываемых поверх друг дружки.
- Bounce Boost. Настраивает яркость отражённых фотонов, информация о которых содержится в слое с GI.
- Atlas Size. Тут указывается размер текстурных атласов с “запечённым” освещением. Если вы делаете игру для мобильных устройств прямиком из 19-го века, то есть смысл выставлять здесь 1024, так как текстуры размером в 2048 не поддерживаются очень старыми устройствами. В противном случае я рекомендую ставить 2048, его поддерживают практически все устройства последних лет. Как вы понимаете, чем меньше размер одного атласа, тем больше придётся их делать. Если вы знакомы с термином Draw Call, то вам не составит труда предугадать, что увеличение количества атласов нанесёт удар по производительности. Поэтому если у вас нет специфичных требований, старайтесь рендерить в 2048.
Вкладка — Fog
И, наконец, туман! Fog, то бишь. К рендеру освещения он не имеет никакого отношения, может включаться и выключаться в любое время. Тут всё предельно просто, поэтому берите и экспериментируйте. Скажу лишь, что туман является крайне мощным художественным средством. Вы можете радикально изменять атмосферу сцены посредством тумана, благодаря ему солнечная сцена станет ярче, мрачная — мрачнее.
Кроме того, туман может использоваться как инструмент повышения производительности. Например, вы хотите вдалеке выключить у всех объектов текстуры и скрыть их за туманом. В более старых версиях World of Warcraft, если вы играли, вы не могли не заметить, какой густой там был туман.
Раздел — Lightmaps
Третьим разделом является Lightmaps, где будут расположены отрендеренные “лайтмапы”. Причем если атласов много, в верхней части вкладки вы не сможете увидеть все атласы, скролл в том окошке неактивен. Поэтому смотрим в нижнее и прокручиваем колесиком мышки.
Здесь нам важно увидеть насколько заполнен последний, самый нижний “лайтмап”-атлас. Если он почти пуст, то либо увеличиваем качество “лайтмапа”, чтобы заполнить весь атлас, либо уменьшаем, чтобы атлас оказался пустым и был удален. На картинке ниже изображены два хорошо заполненных атласа, а один — постольку-поскольку.
“Лайтмапы” хранятся в файлах EXR с глубиной в 32 бита.
Light Probes
Ещё я обещал рассказать про Light Probes. Они представляют из себя небольшие сферы, вбирающие в себя информацию об освещении окружающего пространства. Когда таких сфер много, они создают своебразную карту освещённости вашего уровня или локации. Затем они используются для освещения динамических объектов, в которые не “запекается” свет.
Чтобы лучше понять их смысл, дам пример. На вашей сцене находится один Point Light, у которого стоят настройки Baked, то есть он используется для “запечения” света. Вы не делаете его Real-time, потому что это дорого в плане производительности, причём многие мобильные устройства вообще не поддерживают такой источник света. Далее вы “лайтмапите” сцену и видите, что ваш Point Light освещает окружение. Но если вы возьмёте монстра и поставите рядом с источником света, он останется тёмным, потому что принадлежит к классу динамических объектов, а ваш Point Light влияет только на статические.
Теперь вы расставляете вокруг источника света сетку из Light Probes, снова запекаете освещение. И теперь ваш монстр может ходить вокруг Point Light’а и освещаться им! Это крайне эффективный и недорогой способ имитации освещения. Чтобы добавить “пробы” на сцену, заходите в Game Object — Light — Light Probe Group. На сцене появится кубик из четырёх сфер. Для выбора отдельных сфер, используйте ctrl + click. В Inspector появятся несколько кнопок, позволяющие добавлять или удалять сферы. Вы также можете использовать комбинацию ctrl + D для дублирования сфер.
Расставляйте Light Probes аккуратно, размещайте их там, где вы хотите, чтобы они вбирали в себя информацию об освещении, чтобы потом передавать её динамическим объектам. Во избежание графических артефактов и мерцающего света, следите за тем, чтобы Light Probes образовывали ровную, красивую сетку.
Ниже скриншот корректно выставленной сетки. Если приглядеться, можно заметить, что Light Probes выставлены не в случайном порядке, а окружают источники света, стремясь эффективно поймать переход от света к тени и обратно.
Заключение
Напоследок хочу дать совет по созданию моделей окружения под “лайтмаппинг”. Создавая контент для игры, я знал, с какой стороны будет смотреть игровая камера, поэтому ради сомнительной оптимизации удалял задние стенки некоторых объектов. В то время у меня был опыт рендера “лайтмапов”, но только в Maya, а не в Unity. Выяснилось, что при рендере освещения в Unity возле объектов, имеющих дыры, то есть удалённые полигоны, появляются жесткие, хорошо заметные артефакты. Имейте ввиду.
Источник