Как смешать две камеры при путешествии через портал в Unity3D

18

Прежде чем перейти к моему вопросу, я знаю, что наиболее очевидным решением было бы использовать прямоугольник нормализованного вида, однако мне нужны более сложные фигуры, чем прямоугольник, и я обратился к использованию прямоугольника порта просмотра, и, похоже, нет быть моим решением.

РЕДАКТИРОВАТЬ: Некоторые люди были смущены моим вопросом, позвольте мне перейти к более подробной информации. введите описание изображения здесь Происходит следующее: когда игрок переходит на один портал, я создаю клон FPS-контроллера и перемещаю его из другого. Это дает мне две камеры, и вид, который вы видите справа выше. Он просто показывает одну камеру и просматривает портал. Что я хочу, это что-то похожее на этогде камеры смешиваются, чтобы создать иллюзию плавного перехода. То, что я хочу сделать, это удалить все с зеленого изображения проверки слева на изображении ниже, и заменить это другой камерой. Таким образом, вы получаете ту часть изображения камеры А, которая выходит из портала, смешанную с той частью изображения камеры В, которая выходит из другого портала, чтобы получить одно полное изображение. И когда вы перемещаетесь по порталу, срез меняется соответствующим образом.

Я проектировал систему порталов, у меня все есть, включая то, что игрок должен плавно перемещаться по порталу. Моя главная проблема сейчас заключается в том, чтобы получить эффект наложения камеры, который делает Valve. Мне нужно, чтобы две камеры плавно сливались друг с другом, как будто ты высовывал голову через портал. И это не может быть просто прямоугольник, он должен совпадать, однако игрок просматривает портал.

Мой лучший вывод на данный момент - возможно, спроецировать шейдер маски глубины за каждым порталом, а затем сделать камеру из портала, который вы путешествуете, только для глубины. Затем как-то смешайте две камеры. Моя главная проблема - выяснить, как именно я это сделаю, как заставить вторую камеру отображать только то, что находится за пределами портала, а по умолчанию для остальных - камера 1, чтобы получить одну полноэкранную проекцию.

Если бы вы могли дать мне идеи или объяснить, как я могу сделать это с шейдером маски глубины, это было бы огромной помощью. Я буду продолжать работать над этим и обновлять по мере того, как делаю прорывы.

Тимоти Уильямс
источник
5
Можете ли вы рассказать, что такое «эффект наложения камеры, который делает Valve»? Я понял, что для рендеринга портала достаточно одной камеры. В играх от первого лица он прикрепляется к игроку и автоматически преобразуется в новое местоположение при прохождении через портал вместе с игроком. Для рендеринга эффекта портала визуализируется преобразованная копия сцены. Это может быть достигнуто и со второй камерой, но не должно быть необходимости смешивать эти камеры.
msell
1
У меня уже есть визуальные эффекты на отлично. То, что я пытаюсь сделать, это выяснить, как получить эффект от хождения по порталу. У меня уже есть вся графика персонажей и такие плавные движения, мне просто нужно, чтобы она выглядела гладко с точки зрения первого лица.
Тимоти Уильямс
1
Я уверен, что многие люди хотели бы помочь вам с проблемой, если они поняли, что это было. Вы действительно должны объяснить проблему лучше, возможно, добавьте фотографии или даже видео, визуализирующее, что не так.
msell
2
Не могли бы вы добавить ссылку на пример видео эффекта?
Майк Бакстер
2
Что делать, если вы использовали только одну камеру / контроллер FPS? Когда камера перемещается по порталу, вы можете преобразовать ее в новое местоположение и ориентацию. Если рендеринг портала правильный, переход должен быть плавным и не требует смешивания.
msell

Ответы:

6

Понимание проблемы

Из того, что я вижу, проблема, которую вы описываете, является результатом того, что ближняя плоскость камеры пересекает плоскость, определенную порталом. Пока происходит это пересечение, вы можете видеть, что за стеной находится портал.

Это похоже на проблему, возникающую в других играх, когда игрок просто переходит из-под воды в воду. Если камера находится чуть выше воды, эффект постобработки не применяется, чтобы скрыть вид игроков (сделать его темным, размытым и синим). Таким образом, если дно ближнего самолета находится под водой, игрок может ясно видеть под водой.

Если я прав, вы можете подтвердить это, изменив положение этой плоскости при определении матрицы проекции. По мере увеличения расстояния от начала камеры до ближней плоскости проблема также должна возрастать.

Простое решение

Создание ближней плоскости очень близко к камере должно почти устранить эту проблему. Это решение не является полным, но в большинстве случаев дает достаточно хороший результат, и оно эффективно.

Полное решение

Если простое размещение ближней плоскости ближе к камере не устраивает, тогда вы можете создать «маску», чтобы смешать изображения, созданные рендерингом сцены с точки зрения игрока и портала.

Предполагая, что вы разрешаете применять порталы только к плоским поверхностям, вы можете рассчитать линию пересечения между ближней плоскостью камеры и плоскостью, определенной порталом (или стеной, на которой он лежит). Эта строка разделит экран на две части. Определение, на какой стороне линии находится пиксель экрана, позволит вам узнать, какое изображение рендера использовать, изображение портала или изображение с камеры плеера.

Имейте в виду, что если возникает эта проблема, то усечение вида камеры должно быть полностью внутри портала, поэтому линия пересечения всегда будет полностью перерезаться от одного края экрана к другому.

Эта ссылка должна помочь с математикой, чтобы найти строку. Код ниже должен быть примерно правильным.

Линия пересечения определяется с использованием точки на линии и направления линии. Ниже направление пересечения вычисляется с использованием перекрестного произведения нормали портала и направления обзора камеры (нормали ближней плоскости). Точка на линии задается путем наведения луча из точки в ближней плоскости прямо к плоскости портала (вдоль нормали портала) и нахождения точки пересечения.

Vector3 intersectionDir = Vector3.cross(portalNorm, viewDir);
Ray ray = new Ray(camPos + viewDir * camNearPlaneDist, portalNorm);
Vector3 intersectionPos = ray.intersects(new Plane(portalVert1, portalVert2, portalVert3);

Убедитесь, что viewDir является единичным вектором. portalVert1, 2 и 3 - это всего лишь 3 из 4 вершин, используемых для надписи портала или поверхности, на которой он находится. Существуют и другие способы определения плоскости, на которой лежит портал, но я предполагаю, что это наиболее доступная информация.

Если у вас есть эти два вектора для определения линии пересечения, умножьте каждый на вид, а затем на матрицы проекции, чтобы получить их в пространстве экрана.

Затем вы можете использовать шейдер постобработки, чтобы смешать эти изображения. Вы выбираете, какое изображение использовать в каждом пикселе, определяя, на какой стороне разделительной линии находится текущий пиксель. Это делается путем выбора положения пикселя (которое также используется для поиска целевого объекта рендеринга) и выполнения действия;

float d = (pixelX - intersectionPos.X) * intersectionDir.Y - (pixelY - intersectionPos.Y) * intersectionDir.X;

Сторона определяется тем, больше ли d или меньше 0. Если это точно 0, то вы на линии.

Для справки по математике выше см. Это .

Этот метод также можно использовать при создании буфера маски / трафарета глубины для использования перед рендерингом с точки зрения портала. Вы можете создать полноэкранный квад и использовать линию, чтобы нарезать его.

OriginalDaemon
источник
Самолет ближнего клипа был хорошей идеей, но не совсем то, что я искал. Эта вторая часть интересный подход, хотя. В настоящее время я использую шейдер маски глубины для всего, что находится за выходящей плоскостью портала, а затем устанавливаю флажки очистки выходной камеры только на глубину. Это делает так, что любая часть выходящей камеры, выходящая из портала, рисует на экране, а входящая камера рисует на маске глубины, поэтому она создает одно изображение, смешивая части каждой камеры, выступающей из нее. соответствующий портал. Единственная проблема в том, что у меня возникают небольшие проблемы с отсечкой, и, как
Тимоти Уильямс,
небольшой рывок, когда игрок проходит. Эта идея, которую вы воспитали, звучит довольно многообещающе. Поэтому, по сути, мне нужно вычислить линию вдоль экрана, по которой камера пересекает плоскость и плоскость портала, направление показывает, в каком направлении идет линия, а точка - это различные точки линии. Как тогда я определю в шейдере / скрипте, на какой стороне разделительной линии лежит пиксель?
Тимоти Уильямс
Я немного обновил ответ, чтобы дать базовый код. Обязательно попробуйте изменить вид вблизи расстояния отсечения, чтобы подтвердить проблему. Этого может быть как можно меньше. Помните, работайте, работайте правильно, а потом работайте быстро.
OriginalDaemon
1
Связанная статья: en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal_Smooth
msell
Я проверил изменение расстояния до ближней плоскости отсечения, это немного улучшило проблему, но, как написала статья Мелла, утверждает, что это не решает проблему при пролистывании. Я все еще чувствую, что линия пересечения может работать, поэтому я собираюсь попробовать это. Я также посмотрю немного подробнее на ту статью, которую Мелл опубликовал. В конце концов, все будет зависеть от того, будет ли маска глубины быстрее или эта линия пересечения быстрее
Тимоти Уильямс,
3

Предложенные ответы были очень хорошими, но в итоге я выбрал другую технику, используя маску глубины.

Что вы делаете, это берете ЭТОТ скрипт и шейдер, вы помещаете скрипт на каждый объект с рендером в вашей сцене и устанавливаете очередь рендеринга на 3020 (я опубликую скрипт, чтобы упростить это позже).

Затем вы создаете коробку плоскостей (все обращены внутрь, на картинке вы не видите боковую сторону коробки, ближайшую к вам, но когда вы внутри коробки, все, что вы должны видеть, - серый) за ОБАМИ ваших порталов вот так: введите описание изображения здесь и установите их на специальный слой (я выбрал «DepthMask» для моего), затем вы добавляете материал с шейдером выше. введите описание изображения здесь

Затем вы берете основную камеру и снимаете свой специальный слой с маски для отбраковки (я снял флажок со слоем DepthMask) и устанавливаете его глубину на 0. введите описание изображения здесь

Затем, когда вы телепортируетесь через камеру и клонируете камеру, установите для флагов очистки другой камеры значение «Только глубина», а его глубина равна 1. введите описание изображения здесь

Затем вы получаете плавный экран, смешанный между двумя видами камеры.

Тимоти Уильямс
источник