Чем GearVR отличается от картонной коробки, или погоня за latency

    Disclaimer: пост написан на основе изрядно отредактированных логов чата closedcircles.com, отсюда и стиль изложения, и наличие уточняющих вопросов.


    image


    Главный термин который надо знать относительно VR — motion-to-photon latency.
    Иначе говоря, задержка между поворотом головы и последним фотоном изображения (отрисованного с ракурса нового положения головы) покинувшим экран.
    Эмпирически выведено что motion-to-photon latency 20 msec и ниже позволяет достигать presence — т.е. ощущения что двигаешь головой в виртуальном мире.
    Важны ли значения меньше 20 ms или нет — непонятно, но в общем цель — достигнуть 20.
    GearVR правдами и неправдами достигает, и я расскажу как.


    Заранее прошу извинить за свободное использование английских терминов вперемешку с транслитерированными и переведенными.


    GearVR это если кто не знает headset в который втыкается телефон. В самом хедсете экрана нет — там есть линзы и IMU.
    IMU это стандартное gyroscope + accelerometer. Есть ли в GearVR магнетометр я точно не знаю, вроде нет — но в любом случае на практике магнетометр не очень важен.
    Есть стандартные способы получать ориентацию устройства с помощью gyro и accelerometer, я останавливаться на этом не буду.


    Важный момент: В GearVR свой IMU, который дает новые данные об ориентации на частоте 1000 Hz с минимальным latency (скорее всего порядка 1 ms).
    Это в разы лучше встроенных сенсоров в телефонах (в Samsung Note 5 gyro частоты 200 Hz и latency 10-15 ms).


    А как оно питается? От телефона?
    Насколько я понимаю, питается от телефона через USB — там собственно почти железа внутри нет, так что наверное расход минимальный.

    Значит, базовая расстановка — у нас есть IMU данные, мы их прочитали в начале кадра и надо отрендерить два кадра (стерео картинку). В GearVR нет positional tracking — мы знаем только ориентацию головы.


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


    Как уже сказано, в GearVR есть две линзы — по одной на глаз. Линзы нужны по двум причинам:


    1. Увеличение FOV. Если померять FOV экрана прилепленного к голове то получается недостаточно высокое значение — хочется 90+ градусов на каждый глаз, чтобы экран мог быть достаточно маленьким.
    2. Изменение оптического фокусного расстояния.
      Если не было бы линзы, то разные пиксели были бы в разных фокальных точках т.к. экран очень близко и разница в расстояниях разных пикселей достаточно существенная.

    Линза "выпрямляет" лучи идущие из глаза, получается ощущение оптического фокуса на бесконечности:
    image


    Собственно получается так что линза с такими параметрами имеет достаточно значительный distortion — если просто отрендерить картинку в оба глаза то объекты будут заметно искажаться; чем дальше от центра линзы (глаза), тем больше.
    Поэтому мы возьмем картинку полученную стандартным 3D рендером и ее при выводе на экран исказим, чтобы после искажения линзы получилось примерно то же самое.


    Для этого обычно рисуется distortion mesh который выглядит примерно так:
    image


    Плюс еще если у вас достаточно много лишнего времени на GPU, то можно в этом же проходе попытаться скорректировать chromatic aberration
    (который тоже получается из-за свойств линзы).
    На практике на GearVR по умолчанию этот фильтр отключен — чтобы его скомпенсировать надо вместо 1 текстурной выборки в шейдере делать 3, а это мобильное железо.


    Итак, вводная закончена, давайте разбираться с latency :)


    В предложенной схеме никаких 20 ms не будет и вообще все будет очень плохо.
    Потому что...


    • В начале кадра мы прочитали IMU data — с скажем 1 ms latency;
    • Потом мы собрали матрицы кадра, отрендерили сцену — это в целом длительный процесс, особенно с учетом качества OpenGL драйверов на Android;
      (это еще 16 мс например если 60 FPS render...)
    • Потом мы отдали кадр на GPU — он долго и упорно этот самый кадр рисует, и потом делает distortion чтобы получить финальную картинку;
      (это еще 16 ms)
    • Потом запускается display scan-out!

    Дисплей понятно совсем не CRT, но при этом понятие "луча" считывающего данные все еще осталось — контроллер дисплея считывает дисплей сканлайн за сканлайном и зажигает пиксели.
    И чтобы считать весь дисплей — уходит 16 мс.
    Сканлайны на телефоне обычно "короткие" — когда вы используете VR то телефон в ландшафтном режиме, и сканлайны это вертикальные полосочки, идущие слева направо (ну или справа налево если телефон перевернут...)
    Соответственно самый левый сканлайн (в левом глазу) обновляется на 16 мс раньше чем самый правый (в правом глазу).


    • И наконец, есть еще одна радость:
      Описанный механизм это стандартный double buffering…
      В доблестной операционной системе на самом деле triple buffering.
      Т.е. когда GPU дорисовывает картинку то она отдается не на дисплей а в композитор, который ее возможно совмещает с другими окнами итп.
      И получается еще один кадр (16 ms) задержки.

    В итоге короче получилось что-то типа 65 ms latency
    Что невообразимо больше чем 20.


    Плюс есть еще одна проблема…
    Обычно дисплей работает в full persistence mode — а именно, сканлайн зажигается новыми цветами, и потом остается в таком режиме фактически весь кадр — т.е. 16 мс.
    Оказывается, что за 16 мс можно достаточно далеко повернуть голову, и в результате этот сканлайн глазом регистрируется в разных точках retina с одним и тем же цветом.
    И получается smearing при повороте головы.


    Значит если все это не побеждать — GearVR игры выглядели бы как Google Cardboard.
    Надо побеждать.


    Ключевой технологией является технология которую Oculus называет Time Warp.
    Еще она называется reprojection, и наверное как-нибудь еще, но мне нравится слово timewarp.
    Идея в следующем — если взять картинку отрендеренную камерой С, потом взять камеру C' которая является камерой C повернутой (но не смещенной) на не очень большое расстояние (единицы-десятки градусов), и отрендерить ей картинку…
    То оказывается что вторую картинку из первой можно получить простым 2D преобразованием.


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


    Если зафиксировать матрицы и поворачивать голову влево-вправо то на небольших углах поворота тот факт что ты матрицы зафиксировал неочевиден.
    Это собственно главный тест того что time warp работает корректно
    (зафиксировал матрицы своего рендера и смотришь можно ли плюс-минус 5 градусов вертеть головой).
    Можно и больше чем 5 градусов но там уже много информации брать неоткуда поэтому большая часть экрана становится черной.
    Собственно "трясти девайс" это стандартный stress test для хедсетов в которых есть positional tracking — фиксируешь голову а дальше руками высокочастотно сдвигаешь хедсет на голове влево-вправо, и значит картинка должна быть стабильной — для этого собственно и надо sub-20 ms (ну и качественный трекинг).


    Слушай, а если на Gear VR рендерить с фиксированной матрицей вью\проджекшен и включить репроджекшен, а потом начать трясти девайс, картинка на нем трясется?
    Ммм, "трясти" — плохо т.к. нет positional tracking и что будет непонятно
    Ну если нет positional tracking, то тряска — это будет просто изменение угла, пускай даже маленькое.
    Ну да, но в реальном мире будет меняться позиция а в хедсете нет — т.е. стабильной картинки не получится.
    Можно пробовать высокочастотно крутить голову влево-вправо если шея не отвалится :)

    Timewarp делается просто — мы уже рисуем тот самый distortion mesh.
    Поэтому можно просто в вершинном шейдере "повернуть" текстурные координаты (в 3D пространстве).
    Пиксельный шейдер не меняется, timewarp получается фактически бесплатным.


    На сколько поворачивать?
    На разницу между поворотом головы сейчас и поворотом головы с которым была отрисована исходная картинка.
    Чем больше поворот — тем больше будет пустого пространства, его можно заполнять черным цветом
    (или можно делать clamp адресацию, на небольших углах поворота получается чуть лучше чем черное, но на больших получается странное).


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


    Сначала разберемся с full persistence — это технически не влияет на motion-to-photon, но таки надо убирать.
    Для телефонов которые поддерживает GearVR написан специальный драйвер дисплея который включает low persistence mode:
    Каждый сканлайн зажигается как раньше нужными цветами, а дальше почти сразу — я точно не знаю через сколько, но скажем 3-4 ms — тухнет (становится черным).
    Оказывается что достаточно большое количество людей в силу особенностей восприятия не замечают "моргания".
    Говорят что граница восприятия варьируется от где-то 50 Hz моргания до 85 Hz — что является одной из главных причин почему десктопные VR хедсеты (Rift/Vive) работают с частотой 90 Hz.
    Плюс low persistence в хедсете воспринимается лучше чем просто моргающая с частотой 60 Hz панель в реальном мире, потому что вроде бы моргает все что ты видишь, и мозг адаптируется...


    Reference links и видео:
    https://www.youtube.com/watch?v=_FlV6pgwlrk
    https://en.wikipedia.org/wiki/Persistence_of_vision
    https://en.wikipedia.org/wiki/Flicker_fusion_threshold


    Ааа, то есть потому что мы уже "убрали" изображение (погасили экран), то это лучше воспринимается? А проблема — это когда он горит все 16 мс, а голова двигается?
    Так точно.
    Есть штука которая называется vestibulo ocular reflex:
    Когда ты поворачиваешь голову у тебя автоматически глаз поворачивается в обратную сторону.
    Поэтому при поворотах головы ты можешь фиксировать глаза на объекте и например читать при не очень сильных поворотах без проблем.
    И значит если у тебя пиксели горят длительное время, то при проекции на retina одного пикселя получается полосочка из-за поворота глаза и получается smearing / ghosting.
    А если пиксель сразу почти выключать то smearing не появляется, и ввиду каких-то особенностей зрения высокочастотное моргание как моргание не воспринимается — я не знаю конкретно почему.
    VOR это вообще крутая штука, там натурально напрямую соединен вестибулярный аппарат с глазными мышцами.
    Участия мозга практически не требуется, и ultra low latency :)

    Теперь при движении головой у нас больше нет smearing, но все еще есть 65 ms latency…
    Давайте теперь разберемся как на самом деле в GearVR работает рендер.
    То что я написал выше про то что в начале рендер кадра мы читаем данные с IMU, потом генерируем OpenGL команды и потом отдаем их GPU который рисует кадр — остается валидным.
    Это игровой тред и игровой GL контекст.


    Есть еще один тред который создает GearVR SDK и у него есть свой GL context, работающий в high priority режиме
    (на новых версиях Android такой контекст можно теперь создать самому с помощью EGL расширения).
    High priority режим означает что команды, отданные GPU на этом контексте, начнут исполняться GPU практически сразу.


    Я не знаю деталей GPU scheduling на конкретно GPU которые поддерживают GearVR — предположу, что там preemption granularity это draw call — т.е. если у вас нет огромных 10 msec draw calls то можно за одну-две миллисекунды закончить текущий и начать следующий.
    На десктопном GPU у NVidia эта гранулярность обычно в draw call а на AMD если я не ошибаюсь 1 wave (для compute), ну и десктопные вендоры работают над улучшением т.к. эта фича тоже важна на десктопном VR...


    Вторая особенность этого VR контекста в том…
    Что он рисует сразу в front buffer — в тот самый буфер из которого происходит scan out — таким образом пропуская все композиторы и прочую ерунду.
    Как мы уже разобрались, scan out занимает 16 мс и идет по сканлайнам один за другим в строгом порядке.
    Сканлайны это вертикальные полоски которые идут слева направо (в ландшафтном режиме), поэтому половина полосок содержат картинку из левого глаза (сканируются за 8 мс), а вторая половина полосок содержит картинку из правого глаза (сканируется за 8 мс).
    А значит можно попробовать рисовать в правый глаз пока дисплей сканирует левый и наоборот.


    Отмечу на всякий случай — это не означает что мы будем рисовать прямо треугольники из кадра игры!
    Тут нужен очень аккуратный тайминг и четкие гарантии, поэтому игра там как получится рисует кадр, а VR контекст будет его корректировать с помощью time warp.


    Итак, этот самый VR тред просыпается дважды — когда vsync интервал начался, и через 8 мс после этого (в середине scan out).
    Читает свежие IMU данные (с latency 1 ms), а дальше генерирует две матрицы корректирующего поворота.


    Почему две?
    Из-за scan out левый сканлайн левого глаза и правый сканлайн левого глаза разнесены во времени на 8 мс (с точки зрения photon emission time), поэтому в идеале надо их корректировать по-разному.
    Поэтому мы читаем данные IMU (latency 1 ms), и генерируем две ориентации головы используя gyroscope данные для prediction вперед.
    Первую мы предиктим вперед на 8 мс, вторую на 16 мс (сейчас будет понятно почему).


    Потом сабмитим draw call в high priority context в котором половина того distortion mesh сверху для нужного глаза и надеемся что GPU его достаточно быстро подберет и отрисует.
    Через 8 мс после того как мы сгенерировали ориентации scan out дойдет до той части экрана в которую мы только что нарисовали данные и начнет ее показывать.
    В итоге полная latency до photon emission крайнего слева сканлайна каждого глаза получается примерно 9 ms, а крайнего справа — примерно 17 ms.


    (те кто 30 лет назад на Amiga писали race-the-beam rasterizers — прослезитесь)


    Собственно если порезать distortion mesh на вертикальные полосочки и иметь более четкие timing гарантии — как я понимаю, с текущим GPU это невозможно — то можно было бы уменьшать motion-to-photon до <10 ms.
    Как видно, половина (8 ms) текущей latency это типа safety буфер чтобы уложиться и засабмитить draw call на GPU и чтобы он его отрисовал, и половина — это худший scanout latency для сканлайна.
    Если резать на полосочки и иметь более четкий тайминг то можно это попробовать решать.
    Или прямо интегрировать time warp в scanout контроллер, операция warp — это просто билинейный семплинг текстуры, не очень сложно.
    Но по большому счету текущий latency — good enough. Если увеличить частоту дисплея до 90 Hz чтобы убрать проблемы с морганием для более чувствительных людей, то получится на той же технологии сразу примерно 10 ms.


    Да, 8 ms это вообще говоря произвольный буфер
    Можно теоретически и меньше
    Теоретически можно меньше, практически заметно меньше наверное становится опасно.
    Если preemption на draw call basis то надо учитывать это тоже
    Особенно короче в VR на mobile есть тенденция запихивать всю сцену в 1-2 draw calls
    Потому что OpenGL медленный, Unity медленный, итп.

    Итого, проснулись сразу после vsync — в это время scan out начал процессить левый глаз — и нарисовали правый глаз в front buffer.
    Потом заснули до середины vsync interval, проснулись — в это время scan out начал процессить правый глаз — и нарисовали левый глаз в front buffer.
    Ad infinitum.


    Отмечу, time warp имеет забавную проблему…
    Он умеет только довернуть картинку.
    Не умеет ее смещать — при смещении начинаются проблемы disocclusion, нужен depth buffer, больше ресурсов итп.
    Но на самом деле глаза два, и когда вы поворачиваете голову — глаза смещаются и поворачиваются одновременно.


    Поэтому чем больше timewarp коррекция тем более неправильной получается stereo картинка и тем сложнее фокусироваться.
    На практике получается что time warp на 20-30 msec к видимым проблемам не приводит, кроме как при огромных скоростях поворота где convergence перестает работать, наверное.


    Еще пара моментов которые GearVR умеет делать, и которые в обычном Андроиде невозможны...


    Во-первых, можно включить realtime приоритет своему рендер потоку (ну и он включается VR потоку)
    Чтобы всякие там потоки garbage collection не очень мешали.


    Во-вторых, можно включить (точнее, нужно) fixed clock frequency.
    По-умолчанию частота CPU и GPU варьируется в зависимости от нагрузки и прочих факторов.
    На практике в Андроиде эти механизмы работают очень странно, и могут привести к тому что нагрузка которая должна укладываться в 16 ms на кадр несколько секунд подряд не укладывается.
    Поэтому SDK отключает динамический adjustment и позволяет выбрать приложению фиксированные frequency scales для CPU/GPU отдельно.


    Вот, я значит уточню. Что весь этот цикл — он для этого специального треда про time warp
    А собственно рендер приложения ему параллелен
    Да, я где-то там выше это писал. Рендер тред взаимодействует с этим time warp тредом через функцию "я закончил сабмитить на GPU команды для следующего кадра, держи его".
    А так два независимых треда и два фактически независимых контекста (ну, наверное в первый контекст вставляются fences чтобы не иметь проблем с синхронизацией).
    И в приложении все ещё может быть и 16 msec на CPU в драйвере, и 16 msec на отрисовку
    В принципе может. Может быть и 40 ms на CPU. :)
    Вот до каких чисел нужно это уменьшать, чтобы остальное вывозил time warp?
    Тут сказать сложно однозначно. Очень зависит от контента. В целом Oculus рекомендует держать стабильные 60 fps (16 ms cpu / gpu) и рассчитывать на time warp для убирания этих лишних 20-30 ms latency, и для сглаживания внезапных frame spikes.
    Но если у тебя контент плюс-минус статический — например, представь себе adventure game — то в SDK есть режим в котором они ожидают что ты отдаешь им кадры раз в 33 ms а не в 16.
    И time warp работает почти идеально (почти — т.к. см. выше про движение глаз при поворотах)
    60 FPS, но 32 msec latency, ага?
    20-30, там зависит от того как конкретно работает драйвер для GPU который обычно tiled, насколько быстро ты можешь засабмитить все draw calls для первого frame buffer и т.п.
    Но в целом 32.
    Ты это будешь в основном видеть на позициях других объектов, если будешь.
    Т.е. это не отличается от стандартных вопросов latency в обычных играх — реакция от нажатия на какую-нибудь клавишу до движения и т.п., это все не так критично как head tracking.

    А, еще забыл!
    Про Cardboard.
    Вот как видно из вышеперечисленного — есть ровно ОДИН момент в hardware у GearVR.
    Хорошие сенсоры с маленьким latency и большим refresh rate.
    Все остальное — software.
    (есть еще линзы но в GearVR линзы насколько я понимаю — ничем не выделяются, в cardboard девайсах такие же считай)


    А про это можно подробно где-то почитать? Про линзу саму. Мне интересно, почему с объектами, которые совсем близко получается фигня. Там левая-правая картинки расходятся так сильно, что я не могу сфокусироваться. А на реальном объекте — могу. Легко тестить на HTC Vive — контроллер к шлему подносишь, потом шлем снимаешь и на него же смотришь в реале.
    Там есть проблема которая называется vergence-accomodation conflict, может быть из-за этого…
    Vergence — это феномен при котором глаза поворачиваются так чтобы смотреть на объект:
    Если объект далеко то глаза смотрят прямо;
    Если объект совсем близко то они поворачиваются к носу например если объект перед носом.
    Accomodation — это та самая фокусировка зрения, там изменяются оптические свойства глаза чтобы фокусироваться (https://en.wikipedia.org/wiki/Accommodation_(eye) ).
    И вот значит в VR происходит следующая штука:
    Vergence работает корректно т.к. каждому глазу дается своя картинка, и если объект близко то в левом и правом глазах разные изображения — объект сильно смещен и глаза поворачиваются как надо.
    А accomodation не работает т.к. линза одна и она не настраивается никак поэтому все объекты на оптической бесконечности.
    Этот конфликт разными людьми резолвится по-разному, ну и чем ближе объект тем больше конфликт.

    Судя по моим экспериментам с сенсорами на разных телефонах с т.з. latency…
    У Samsung и Apple трекинг заметно хуже, но у Nexus 6 трекинг хуже но уже в пределах разумного.
    (ЕМНИП 4ms refresh interval, avg 3 ms latency)
    Т.е. на Nexus 6 — можно делать все что я написал выше и иметь experience натурально сравнимый с GearVR, но в картонной коробке.
    Проблема в том что практически все что я написал выше не сделать из user mode — нужно патчить ядро и драйвера.
    Так что авторы приложений этого делать не могут, но вот Гугл — вполне.


    игрался я вчера как раз на Gear VR — на знаю кому как, но меня мутит, хотя на осознанном уровне я лага не замечаю
    ну и пиксели громадные!
    Главная проблема GearVR с т.з. motion sickness — отсутствие positional tracking.
    Когда ты двигаешь голову, картинка это движение не отражает — это порождает конфликт между вестибулярной и оптической системой
    Были слухи, что направления ресеча на будущее в Окулусе — это positional tracking для mobile и AR
    Ну я не удивлен, positional tracking это missing feature #1, #2 и #3 в gear.
    #4 наверное full RGB display
    Пока все успешные подходы к positional tracking требуют внешней камеры.
    Или кучи камер на хедсете как в HoloLens…
    вот я пробовал оба что rift dk2 что gear vr — одинаково показались бесполезной игрушкой
    ну у меня еще косоглазие
    У меня тоже, это лично мне не очень мешает.
    Это то что я там выше писал про convergence
    Лично мне плюс-минус пофиг какой там IPD в камерах :)
    У меня большая часть восприятия через один из глаз, не через оба — смотря на каком "сфокусируешься"
    ага — или я 3д плохо вижу
    у меня было ощущение как будто я внутри проекционной сферы
    а не внутри 3д мира
    Кстати возможно что для людей с косоглазием positional tracking более критичен по-умолчанию — когда у тебя есть стерео зрение то ты расстояние до объектов воспринимаешь собственно им, а когда оно не очень хорошее то главный visual cue это параллакс
    А параллакс получается в основном от движения головы
    Особенно в gunjack где туррель вокруг тебя
    Но тут я слегка out of my depth, не очень хорошо представляю значимость разных факторов восприятия, так что точно не уверен.
    Я в целом согласен что меня лично GearVR не очень вставлял, в отличие от десктопных experiences.
    Метки:
    Поделиться публикацией
    Комментарии 14
    • +2
      В этой каше весьма много любопытного. Спасибо.
      Видимо не зря я отложил свой VR experience до следующих продакшн ревизий.
      Не знал, что нынешние VR устройства не умеют отслеживать позицию головы.
      • 0
        Отсутствие positional tracking — это недостаток всех текущих мобильных VR устройств.
        Все не-мобильные устройства — Oculus Rift, HTC Vive, PSVR — имеют positional tracking.

        Проблема в том что существующие технологии которые достаточно хороши чтобы их можно было положить в основу продукта требуют внешних камер (Oculus Rift / PSVR), внешних лазерных излучателей (HTC Vive) либо большого количества хитрых камер в самом устройстве (Hololens). Для маленькой дешевой коробочки в которую вставляется телефон это все не очень практично.

        Наверняка Oculus работает в этом направлении, будет интересно — но я не ожидаю никаких новостей в мире mobile positional tracking в 2016.
        • 0
          В статье говорится конкретно про GearVR, oculus и htc vive насколько мне известно данной проблемы не имеют.
          • 0
            Кстати, отсутствие отслеживания смены позиции (т.е. только угол) могут позволить нехило соптимизировать рендер, поправьте меня, в чем я не прав.

            Основная логика работы очков — генерировать необходимое изображение 'из трехугольников' (точнее собственно из мира, ну возможно какая то посчитанная ранее информация конечно используется), каждый раз заново…

            Давайте для каждого глаза считать поверхность сферы (максимально простая 3D сцена), на которые проецируется наш игровой мир, в своем потоке, почти никак не зависящий от шлема. Это возможно именно благодаря отсутствию сдвига положения глаз (конечно же внутри игрового мира двигаться ничто не мешает, но это движение с другими требованиями к скорости).
            На экраны шлема мы максимально быстро отображаем эти сферы, в которых уже должны быть исправлены хроматические аберации, а это значит не нужны лишние проходы,… и мы вполне укладываемся в 20мс.

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

            p.s. кстати ведь вовсю используется предугадывание движения, можно считать следующий кадр заранее.
            • 0
              Я не очень понял про сферы, но ощущение что описано нечто эквивалентное timewarp… :)

              Про предугадывание. Безусловно, все используют prediction. Главная проблема в том что движение головы предсказуемо фактически только на линейных участках. И гарантированно непредсказуемо в самом начале движения (резкие повороты головы). Поэтому prediction несколько улучшает tracking, и те самые последние 10-15 ms им можно «убирать», но если latency условно 40 ms, то prediction не может их скрыть так чтобы было не заметно.
              • 0
                А я не понял про timewarp
                чтобы объяснить на пальцах о чем я говорю… представьте вы сидите перед сферическим экраном, на который проецируется виртуальный мир (на хабре кстати были статьи про такие), они дают неплохой эффект погружения, и беда только с отсутствием стереоэефекта, фиксированным фокусным расстоянием тем более находящимся близко к глазам,… увеличиваем сферу до бесконечности (не обязательно) и получим то о чем я говорю, только стреофект тут есть, так как каждый глаз видит свою сферу.

                Самое главное, уменьшить latency при поворотах головы! т.е. уменьшить объем расчетов за счет упрощения сцены до сферы из нескольких сотен трехугольников. Само собой, считать мир всеравно придется, но уже с меньшими требованиями!
                p.s. а еще именно так на шлем выводится 360 видео (я думаю)… так какая разница то
                • 0
                  Ага, математика time warp — такая же. На «сферу» проецируется изображение полученное рендером из одного положения головы, грубо говоря. Вместо сферы рисуется тот самый distortion mesh, и математика — в шейдере, но иначе все так.

                  Собственно действительно есть в GearVR режим когда вместо того чтобы рисовать 3д сцену и отдавать 2д картинку в time warp, можно в time warp сразу отдать cubemap — 6 2д картинок составляющих куб. Примерно так работает видео.
                  • 0
                    а искажения на кубе не будут видны? особенно при повороте головы!
          • +2
            Отличная статья. Спасибо.
            Любопытно было узнать детали, о которых либо не задумывался, либо только догадывался.
            • 0
              Каждый сканлайн зажигается как раньше нужными цветами, а дальше почти сразу — я точно не знаю через сколько, но скажем 3-4 ms — тухнет (становится черным).

              А я бы попробовал научить электронику дисплея делать синхронный сдвиг всех пикселей в любом направлении. А мерцание 60 Hz мне лично в эпоху crt здорово портило жизнь.
              • 0
                С 60 Hz люди бьются на три группы:
                — Недостаточно чувствительные — не видят мерцания вообще
                — Достаточно чувствительные чтобы видеть мерцание смотря на телефон (в GearVR есть такой режим при котором low persistence mode включается прямо в операционной системе без всякого VR), но недостаточно чтобы видеть его в VR
                — Достаточно чувствительные чтобы видеть мерцание везде

                Насколько я знаю, пояснение второго пункта условно в отсутствие reference point — в VR мерцает ВСЕ :)

                Говорят, порог чувствительности примерно 85 Hz — т.е. людей которые видят мерцание на 90 Hz исчезающе мало. Так что проблема в целом решается более высоким refresh rate (который все равно надо бы делать чтобы уменьшать latency до time warp и иметь меньше проблем с его артефактами — например, для устройств с positional tracking time warp компенсирует целиком повороты, но ничего не делает для движений головы — поэтому надо базовую latency вытягивать в районе 20 ms без time warp. У Oculus Rift и HTC Vive это в целом получается)
                • 0
                  100Hz это 10мс задержки, за которые стоит побороться.
              • +3
                Извините, за критиканство, но практически все термины, которые вы оставили на английском, имеют простой и общепринятый перевод: гироскоп, акселерометр, инерциальный датчик и т. д. Да и «good enough» с «experiences» как-то странно смотрятся. Стиль стилем, но будто «Заводной апельсин» читаешь. А в целом статья интересная, спасибо!
                • 0
                  Да, я в курсе, поэтому и комментарий в начале статьи оставил. Я в основном говорю и пишу на английском, поэтому в свободном полете мысли сложно автоматически переводить, особенно когда четко не знаешь перевод (как перевести experiences? :). Надеюсь в целом не слишком режет глаз!

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.