Перспективный обзор для разработчиков WebXR
Поскольку WebXR использует WebGL для отрисовки представлений, формирующих 3D-среду, отображаемую с помощью XR-оборудования, легко предположить, что вопросы, связанные с перспективой, идентичны тем, что встречаются в любом проекте WebGL. В основном это так, но есть несколько конкретных тем, которые необходимо пересмотреть, и некоторые дополнительные рекомендации, которые следует учитывать, чтобы приложение выглядело правильно и, что более важно, 3D-мир не вызывал у людей головокружение или другие эффекты, которые могут возникать, когда то, что видят, не соответствует тому, чего ожидает мозг от реальности.
В этой статье мы рассматриваем сценарии, в которых способ, которым ваш проект вычисляет, применяет и рассматривает перспективу, может отличаться от кода, написанного для приложений, не связанных с XR.
Проблемы с объемом обзора
Каждый сеанс WebXR, представленный объектом XRSession, предлагает набор параметров, которые можно настроить, создав новый объект XRRenderState и активировав обновленное состояние, вызвав метод сеанса updateRenderState() для замены текущей конфигурации.
Большинство этих значений определяет объем обзора XR-устройства; то есть подмножество визуального поля устройства, которое следует отрисовать. Объем обзора можно представить с помощью четырёх ключевых данных: угла поля зрения, коэффициента пропорциональности отрисовываемого изображения и расстояний до ближней и дальней плоскостей обрезания.
Добро пожаловать в матрицу проекции
Большую часть времени вы будете использовать модель перспективной проекции, поэтому её матрица проекции называется матрицей перспективной проекции. Эта матрица используется для отображения каждого пикселя из 3D виртуального мира в точку в 2D буфере заднего плана для отображаемого вида.
В стандартных ситуациях вы можете и должны получить матрицу перспективной проекции непосредственно из отображаемого вида. Свойство XRView объекта projectionMatrix содержит матрицу проекции, представляющую перспективу вида, и практически всегда следует использовать её без изменений. Внесение изменений в матрицу проекции, предоставленную XRView, вероятно, приведёт к искажению или плохому совмещению отрисованного содержимого относительно реального ландшафта; это может быть достаточно существенным, чтобы вызвать болезнь виртуальной реальности у некоторых ваших пользователей.
Например, если ваше приложение использует WebGL-униформу с именем uProjectionMatrix для передачи матрицы проекции в ваши шейдеры, вы можете использовать такой код для передачи матрицы проекции для view, который в настоящее время отображается:
gl.uniformMatrix4fv(uProjectionMatrix, false, view.projectionMatrix);
Настройка матрицы проекции
Хотя обычно следует избегать ручного построения или изменения матрицы проекции, предоставленной видом, вы можете это сделать в некоторых ситуациях. Наиболее распространённая причина, по которой это может быть целесообразно, заключается в изменении расстояний до ближней и дальней плоскостей обрезания для увеличения или уменьшения количества отображаемых полигонов по причинам производительности. Когда игры предлагают настройки для регулировки расстояния до вида, это делается путём изменения этих значений расстояния.
В режиме погружения система WebXR получает стандартный объём обзора от программного обеспечения, предоставленного поставщиком оборудования. Этот объём обзора основан на некотором сочетании линз устройства, аппаратного обеспечения дисплея и камер. В этом расчёте участвуют все, от размера датчика изображения до фокусного расстояния линзы.
Погружённые в опыт используют определяемые аппаратным обеспечением поля зрения, фокусные расстояния и так далее, поэтому при использовании погружённого сеанса вы можете изменить только расстояния до ближней и дальней плоскостей обрезания. Это делается путём установки значений свойств XRRenderState depthNear и depthFar.
В режиме встроенного отображения вы также можете изменить поле зрения непосредственно, установив значение свойства renderState inlineVerticalFieldOfView. Это свойство должно быть установлено в значение null для любого погружённого сеанса.
После получения объёма обзора вы можете вычислить матрицу перспективной проекции, которую WebGL использует при отрисовке сцены, используя функцию, подобную этой:
function makePerspectiveMatrix(fieldOfViewInRadians, aspectRatio, near, far) {
const f = 1.0 / Math.tan(fieldOfViewInRadians / 2);
const rangeInv = 1 / (near - far);
return [
f / aspectRatio,
0,
0,
0,
0,
f,
0,
0,
0,
0,
(near + far) * rangeInv,
-1,
0,
0,
near * far * rangeInv * 2,
0,
];
}
Значения near и far получены непосредственно из объёма обзора; это расстояние от начала координат до ближайшей точки ближней плоскости обрезания и дальней плоскости обрезания соответственно. Коэффициент пропорциональности — это значение, полученное путём деления ширины поля зрения на его высоту. Если целевой дисплей использует коэффициент пропорциональности 16:9, значение для aspectRatio должно быть 16/9, или 1,7777777778.
Если вы используете библиотеку или фреймворк, предоставляющие функции математики матриц, в ней почти наверняка будет аналогичная функция. Например, в популярной библиотеке glMatrix вы найдёте её в функции mat4.perspective().
Независимо от источника, после получения матрицы проекции вы можете использовать её при вызове WebGL для отрисовки сцены.
Согласование с реальностью
В приложениях дополненной реальности (AR) отображаемое содержимое накладывается поверх реального мира. Для этого ваш расчёт перспективы должен соответствовать перспективе зрителя окружающего мира. Если этого не сделать, ваши объекты не будут корректно совмещены с реальностью.
Если матрица перспективной проекции вашей виртуальной камеры не приводит к тому, что виртуальные объекты имеют такую же кажущуюся перспективу, как и реальный мир, то расхождение между виртуальным и физическим мирами может быть резким или, что ещё хуже, вызвать головокружение, укачивание или другие виды дискомфорта у пользователей вашего приложения.
Ещё одна связанная проблема заключается в том, что если вы используете матрицу перспективы для определения того, где разместить объекты, расхождение между вашей матрицей перспективной проекции и физической перспективой пользователя на мире может привести к тому, что объекты не будут размещены точно. Например, если ваше приложение позволяет пользователю вешать виртуальные картины на стены, но матрица перспективы не совпадает, то размещённые картины могут оказаться не на стене, частично пересекая стену, или с одним концом ближе к стене, чем другой, вместо того, чтобы быть правильно параллельными стене.
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Perspective