18/02/2020

Web (1): RayCasting vs GPU Color Picking (на примере Three.js)

В определённый момент, перед разработчиком графических приложений с использованием OpenGL/WebGL встаёт задача взаимодействия пользователя с объектами. Будь то элементы двухмерного интерфейса (частный случай трёхмерного пространства) или объекты трёхмерной сцены, существует два подхода к решению этой задачи. Первый заключается в поиске объекта, на который указывает мышь математическим (тригонометрическим) расчётом.  Второй — поиск объекта по цвету пикселя, на который пользователь указал мышью. Первый кажется логичным, понятным и красивым, второй — на первый взгляд кажется странным, но у обоих методов есть свои плюсы и минусы и свои области применения.

В этой статье мы рассмотрим два метода выбора объекта на сцене (OpenGL/WebGL на примере Three.js) — RayCasting и GPU Color Pick.

RayCasting — это технология определения пересечения луча с объектом. При определении выбранного объекта — объекта, на который навели мышь, например, выбирается первый объект, с которым произошло пересечение. На самом деле собираются все объекты, с которыми пересёкся луч, а уже мы используем только первый. RayCasting работает на стороне CPU, то есть, не задействует специфические вычислительные мощности GPU. 

В Three.js для этих целей имеется уже разработанный объект THREE.Raycaster. Пользоваться им достаточно просто, в примере, которым я завершу эту статью, этот метод будет представлен. Описывать его механику смысла не вижу — это обычная тригонометрия.

У RayCasting’а есть два минуса:

  1. Он работает медленнее, так как работает на CPU, и в случае, когда у нас много объектов, это может быть очень тяжёлой задачей для центрального процессора. А в современной графике с использованием актуальных методов создания карт (т.н. сцен) количество объектов может быть очень большим.
  2. Он не учитывает факторы текстуры — прозрачность, и просто «выбирает» объекты, которые встречаются лучу (в нашем случае — выбор объекта мышью, луч рассчитывается от камеры), то есть работает исключительно геометрия (математика).

Технология GPU Color Pick заключается в следующем. При создании сцены, все объекты дублируются в другую сцену, обычно называемую PickingScene и связываются некоторыми ID реальных объектов с цветами объектов в PickingScene. Для исключения излишней нагрузки на GPU, PickingScene, как правило, делается очень маленькой (выходной буфер рендеринга очень маленькой площади, это в некоторой степени сокращает время на рендеринг). В нашем случае, по наведению мыши, вызывается функция поиска объекта в PickingScene и затем выбирается ID объекта в реальной сцене. В силу того, что технология GPU Color Pick работает по цвету, она лишена второго минуса RayCasting’а — мы можем использовать альфа-канал в текстурах объектов. Это значит, что мы можем дать пользователю возможность «выбирать» объекты стоящие «за», сквозь «прозрачные» области стоящих «перед». В силу того, что технология GPU Color Pick работает на GPU, а он, в свою очередь очень «заточен» под такие задачи, эта технология работает гораздо быстрее и почти полностью разгружает CPU (на нём остаётся лишь задача соотнести цвета и ID объектов).

У GPU Color Pick (как ни странно) есть два минуса:

  1. Мы не можем получить координаты места «встречи» указателя (здесь это не луч и не вектор) и объекта — только сам объект, так как объект выбирается не геометрией, а цветом.
  2. Подгружается GPU. Это хорошо тем, что разгружается CPU, но может быть плохо, если вычислительные мощности GPU для нас критичны. Плюс, в момент процесса самого Picking’а, нам надо ждать на CPU пока GPU выполнит задачу поиска объекта по цвету.


Все эти технологии, конечно же применяются и на Bare WebGL и на чистом OpenGL.

Чтобы поиграться (работает без Web-сервера):

git clone https://gitlab.com/daftsoft/gpu-color-pick-vs-raycasting