Это длинный ответ, но на самом деле основная предпосылка деления на камеру-z очень проста: чем дальше от вас что-то, тем меньше оно кажется. Также появляются меньшие расстояния между двумя вещами.
Позиции (не требуется чтение, если вы используете Unity!)
Во-первых, вам нужно визуализировать позиции / точки, используя правильную перспективу.
Положения лежат на плоской плоскости. Вы хотите что-то вроде изображения справа ... рассматривайте углы плиток в качестве точек / позиций выборки.
Вот как вы подходите к преобразованию точек:
- Ваша система координат выглядит следующим образом: положительный
z
элемент попадает на экран, а x
слева направо y
бежит вниз. Камера z - это мир z. Это ярлык, который делает это намного проще, чем написание полноценного 3D движка. Даунсайд? Камера не может изменить ориентацию (хотя она может изменить положение).
- Сохраните исходное 3D-положение вашей камеры. Положите это несколько назад (минус
z
) от мирового происхождения.
- Сохраните коллекцию трехмерных точек на плоскости xz (дайте их
y=0
). Постарайтесь центрировать их по всему миру x
, (0,0,0)
начиная с отрицательного, n
чтобы положительного n
. Это делается для центрирования их в окне просмотра, когда начинается рендеринг.
- Считайте, что исходная точка уменьшающейся точки / пиксельного графика является центром экрана.
- Определите расстояние от камеры, на котором 1 единица мирового пространства = 1 пиксель. Это означает, что если вы переместите камеру всего на 1 единицу мирового пространства, любой объект на расстоянии 10 единиц сместится всего на 1 пиксель - довольно далеко! Сохраните это расстояние как константу
K
.
Теперь для каждой точки выполняйте рендеринг в позиции, используя следующую формулу: screenPosition(x,y) = screenOrigin + (worldPosition(x,y) - cameraPosition(x,y)) / ((worldPosition(z) - cameraPosition(z)) * K)
... как вы можете видеть, мы основываем позицию рендера на z
-дистанции между текущей точкой и камерой.
Поиграйте с положением камеры z, пока не увидите рендеринг точек. Но вы увидите, что все точки будут отображаться по центральной линии экрана. Таким образом, мы должны исправить это. Попробуйте K=1
против, K=10
чтобы увидеть разницу.
Теперь вы можете переместить камеру внутрь, y
чтобы увидеть, как ваша камера поднимается выше и ниже плоскости точек (т. Е. Точки будут рендериться, корректно в перспективе, ниже или выше средней линии экрана, соответственно, при перемещении камеры вверх и вниз). ).
Это очень грубые рекомендации. Есть несколько деталей реализации, которые будут зависеть от вас. Первый шаг - просто получить что-то отображаемое, а затем внести изменения. Одна деталь, которая приходит на ум, это то, что если вы хотите, чтобы камера выглядела так, как будто она смотрит вниз, то вам нужно сместить источник рендеринга вверх, ближе к верхней части области просмотра. Другая деталь заключается в том, что ваше расстояние между камерой и точкой может включать отношение триггеров ... Я думаю, использование tan
более реалистичной перспективы. Четко не помните об этом, но вы быстро увидите, выглядит ли перспектива странно и может ли она соответствующим образом адаптироваться. Я не могу быть более конкретным без переписывания образца.
Деформация и масштабирование для рекламных щитов (обязательно)
Теперь, когда вы можете видеть перспективу среди своего набора точечных позиций и можете добавлять, удалять или перемещать (как с символами) позиции по желанию, вам также необходимо применить перспективу к отдельным спрайтам, которые будут внедрены в этих позициях.
В D2 мне всегда казалось, что это простая функция боковой деформации, которая применяется больше к рекламным щитам, которые находятся внизу экрана, чем к верхним, а также больше, когда вы удаляетесь от средней линии, спускающейся вниз. экран.
Может также быть некоторое вертикальное масштабирование, примененное к рекламным щитам, например. деревья становятся короче по сравнению с их ожидаемым масштабом, ближе к нижней части экрана (чтобы это выглядело так, как будто камера смотрит на деревья - я обнаружил, что деревья Тристрама - лучший способ исследовать это безопасно, еще в день;)).
Что бы я сделал, это:
- Работайте с основной функцией масштабирования на основе расстояния от камеры до земли в разных точках. Таким образом, вы будете иметь одинаковое масштабирование для каждой линии сканирования.
- Только после того, как я это сделаю, я смогу посмотреть на боковой перекос - сначала на основе расстояния от средней линии, спускающейся по экрану.
- Наконец, я бы исследовал, как на эту боковую деформацию влияет расстояние вниз по экрану (и у меня возникает ощущение, что в основе этого лежит простое соотношение триггеров).
Правильная перспектива (Не требуется чтение, если вы используете Unity!)
Надеемся, что приведенное выше даст вам правильно расположенные искривленные спрайты (т.е. объекты, которые расположены перпендикулярно плоскости земли, такие как персонажи, деревья, дома).
Тем не менее, вы также должны подумать о том, как заставить основную плитку правильно и плавно деформироваться. И я думаю, вы обнаружите, что именно эта часть, в частности, требовала наличия графического процессора на D2. Я помню, что в системах без графического процессора опция перспективы была отключена. Причиной этого почти наверняка было то, что графический процессор может брать текстуру поверхности и применять к ней коррекцию перспективы очень быстро, без каких-либо сбоев между тайлами и без беспокойства по поводу выполнения неаффинных преобразований в коде приложения, что требует некоторой математической математики и может быть немного дорогостоящим:
У меня есть несколько предложений для вас, чтобы справиться с этим:
- (Unity) Используйте камеру Unity, чтобы обеспечить рендеринг плоской текстурированной поверхности земли, а затем обрабатывайте искажения на билборде отдельно в зависимости от положения на экране.
- Делайте эту логику (или даже всю логику рендеринга) в графических шейдерах.
- Не используйте наземные плитки вообще. Вместо этого просто используйте точечные спрайты - как и сами персонажи - на плоскости одинакового цвета (например, зеленый для травы), чтобы детализация этой плоскости не выглядела скучно. Это увеличит ваши затраты на рендеринг, но это, безусловно, самый простой способ решения этой проблемы.