Russian Qt Forum
Ноябрь 22, 2024, 05:21 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Picking [решено]  (Прочитано 10781 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Июль 21, 2020, 15:29 »

Добрый день

Интересуют все 3 вида выборки: объектов, вертексов и фейсов. Старый код (что я когда-то писал "по Липчаку") конечно полностью развалился и отсыпает ошибки с core profile 3.3. Быстро убедился что пытаться как-то его залатать не удастся. Неск лет назад что-то доделывал и спрашивал на пресловутом gamedev, ничего нового, советовали ту же технику "кодирования цветами".

Идея там проста и привлекательна - давайте нарисуем каждый объект (или вертекс, фейс) "своим" цветом и отрендерим а текстуру. Потом читаем пыксели - и получим что выбрали. Однако все почему-то оговариваются что, мол, "этот подход/метод не лучший". Оно и понятно, соскочили 3D -> 2D, возможности не те.

Ну то ладно, "дефицит концептуальности" я как-нибудь переживу. Но у меня рендерится с AA (samples), а значит цвета пыкселей смешиваются и "декодирование" загнется. Как мне переключаться между контекстами с AA и без - ума не приложу. И данных рисования прорва, реально ли вообще использовать их в др контексте?

А если не "цветом" то как? Сейчас гуглю чтобы представить осмыслить общую картину - но пока грустно. Что посоветуете ?

Спасибо
« Последнее редактирование: Сентябрь 17, 2020, 07:21 от Igors » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #1 : Июль 21, 2020, 16:35 »

Интересуют все 3 вида выборки: объектов, вертексов и фейсов.

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

Идея там проста и привлекательна - давайте нарисуем каждый объект (или вертекс, фейс) "своим" цветом и отрендерим а текстуру. Потом читаем пыксели - и получим что выбрали. Однако все почему-то оговариваются что, мол, "этот подход/метод не лучший". Оно и понятно, соскочили 3D -> 2D, возможности не те.

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

Другой способ - формировать буфер выбора, подобно старому способу ранних версий OpenGL glSelectBuffer, но самостоятельно! glSelectBuffer ооооччееень медленная штука. Формируйте изображение в квадратик 3х3 под координатами мыши о заполняйте его во фрагментном шейдере. Получите перечень всех объектов с глубиной отображения.

Еще способ - формируйте пространственное дерево. Находите ячейку пространства - получаете список потенциальных элементов, ищите пересечение луча с объектами.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #2 : Июль 21, 2020, 17:29 »

Но у меня рендерится с AA (samples), а значит цвета пыкселей смешиваются и "декодирование" загнется. Как мне переключаться между контекстами с AA и без - ума не приложу. И данных рисования прорва, реально ли вообще использовать их в др контексте?

А зачем в другом контексте? Можно рисовать в этом же, только с другими установками и другим наборов шейдерных программ. Ну а если все-таки хотите в другом контексте, то используйте shared context.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Июль 22, 2020, 11:25 »

А зачем в другом контексте? Можно рисовать в этом же, только с другими установками и другим наборов шейдерных программ. Ну а если все-таки хотите в другом контексте, то используйте shared context.
Упрощенно: sampling (в установках формата/контекста) - это (возможно максимальное) число суб-пикселей которые будут считаться для каждого пикселя. Цвет итогового пикселя будет получен осреднением этих суб-пикселей (самплов), отсюда и проблема - "чистый" (заданный) цвет не получить.

Разницы нет никакой, что выбирать. Каждый выбираемый элемент нужно пометить своим идентификатором.
Думаю реализуемо, но мне это не кажется "таким уж простым". Для объекта годится униформ, а вот для фейса или вертекса - не вижу др возможности кроме как прицепить геометрический шейдер и там использовать gl_PrimitiveIDIn

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

Другой способ - формировать буфер выбора, подобно старому способу ранних версий OpenGL glSelectBuffer, но самостоятельно! glSelectBuffer ооооччееень медленная штука. Формируйте изображение в квадратик 3х3 под координатами мыши о заполняйте его во фрагментном шейдере. Получите перечень всех объектов с глубиной отображения.
Здесь не понял. Фрагментный шейдер считает цвет, ну я могу считать только в заданном квадрате, и что с того? Не знаю др способов сохранения посчитанного кроме текстуры (в рамках 3.3)

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

Вообще как-то кисло. Задача стопудово типовая, такие должны решаться "открыл "книгу",  прочитал, реализовал". Собсно так и было до этой вакханалии с шейдерами. А тут кроме этого детского лепета с цветами ничего не видно. Ладно, не буду спешить с выводами, погуглю еще. Спасибо за участие
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #4 : Июль 22, 2020, 19:15 »

Другой способ - формировать буфер выбора, подобно старому способу ранних версий OpenGL glSelectBuffer, но самостоятельно! glSelectBuffer ооооччееень медленная штука. Формируйте изображение в квадратик 3х3 под координатами мыши о заполняйте его во фрагментном шейдере. Получите перечень всех объектов с глубиной отображения.
Здесь не понял. Фрагментный шейдер считает цвет, ну я могу считать только в заданном квадрате, и что с того? Не знаю др способов сохранения посчитанного кроме текстуры (в рамках 3.3)

Мы использовали GL_ARB_shader_storage_buffer_object (OpenGL 4.3) и хранили структуру

Код
C++ (Qt)
struct PixelData
{
uint32_t id;
float depth;
};
 

и использовали атомарный счетчик (https://www.khronos.org/opengl/wiki/Atomic_Counter) для определения позиции записи.

Но идея такая. Складывать такую структуру в 1D Texture. Рисовать всего 1 пиксель, чтобы обеспечить неконкурентный доступ к текстуре. Использовать 4 байта под id и следующие 4 под depth.
Искать в 1D текстуре ближайший ноль на четной позиции и записывать туда пару {id,depth}. В результате на выходе 1D текстура с последовательностью пар. Расскажите, если получится).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Июль 28, 2020, 07:39 »

Мы использовали GL_ARB_shader_storage_buffer_object (OpenGL 4.3) и хранили структуру
Видел (боковым зрением) ф-ции синхронизации для четверки, стало быть и запись там уже есть. Но требования "core 3.3", делать "и так и сяк" - себе дороже. А в 3.3 похоже никаких возможностей что-то "вернуть" из шейдера нема  Плачущий

Ну ладно, буду делать на CPU, пусть медленновато, но не катастрофа. Правда и здесь один из случаев = выбрать только "видимые" (не перекрытые отрисованным) примитивы. Думал отрендерить Z-buffer, но это опять проблемы (точности) пикселей и растеризации, решения не имеют. А рейтрасер в приложении есть (bullet) но тащить/заряжать его - типа "корову на баню".

Пока наметил такой план: при смене view в отдельной нитке строить структуры поиска ну и при клике выбирать (возможно с OpenMP). Что за структуры: думаю перевести все вертексы в экран и по паре сортированных x/y массивов (одна для вертексов, др для фейсов). Хотелось бы конечно использовать мощности GPU (да и вообще более стандартного, канонического решения) - но где ж взять если нету  Плачущий
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #6 : Июль 28, 2020, 17:09 »

И все же мне не понятны следующие моменты:
- что мешает использовать вариант 1 с отображением вертексов, ребер, граней, объектов своим идентификационным цветом в framebuffer без AA и читать пиксели?
- что мешает использовать вариант 2 с отображением вертексов, ребер, граней, объектов своим идентификационным цветом в framebuffer для формирования последовательности PixelData?

И тот и другой способ требуют максимум OpenGL core 3.0. 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Июль 28, 2020, 19:35 »

- что мешает использовать вариант 1 с отображением вертексов, ребер, граней, объектов своим идентификационным цветом в framebuffer без AA и читать пиксели?
Ну вот меш "плотненький", т.е. один пиксель покрывает 2 и более примитивов. И все - приплыли, решений нет. Можно отрендерить в текстуру побольше, ну это так, заплатка до след раза.

- что мешает использовать вариант 2 с отображением вертексов, ребер, граней, объектов своим идентификационным цветом в framebuffer для формирования последовательности PixelData?

И тот и другой способ требуют максимум OpenGL core 3.0.  
Хорошо бы, но как я ее сформирую если могу только рендерить в текстуру (причем пиксель не тот что "я хочу" а только тот "что дали") ?

Edit: и еще (забыл сказать) - да, выбирать "только видимые" нужно, НО выбирать "всех" (под мышей или в рамке) независимо от их перекрытия - тоже нужно. И выходит что "чтение текстуры" недостаточно, все равно нужно городить что-то еще.
« Последнее редактирование: Июль 29, 2020, 07:10 от Igors » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #8 : Июль 29, 2020, 13:38 »

- что мешает использовать вариант 1 с отображением вертексов, ребер, граней, объектов своим идентификационным цветом в framebuffer без AA и читать пиксели?
Ну вот меш "плотненький", т.е. один пиксель покрывает 2 и более примитивов. И все - приплыли, решений нет. Можно отрендерить в текстуру побольше, ну это так, заплатка до след раза.
Рендерят обычно в текстуру равную по размеру отображаемой области, тогда не важно насколько плотный меш. Кто сверху, того и выбираем.

Хорошо бы, но как я ее сформирую если могу только рендерить в текстуру (причем пиксель не тот что "я хочу" а только тот "что дали") ?
Я попробую реализовать пример в свободное время). Но это будет не скоро.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Июль 30, 2020, 07:12 »

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

Хорошо бы, но как я ее сформирую если могу только рендерить в текстуру (причем пиксель не тот что "я хочу" а только тот "что дали") ?
А если "попробывать" реализовать Вашу идею с PixelData чуть по-другому:

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

Thoughts?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июль 31, 2020, 12:02 »

Тут прильнул к матчасти..
- цепляем геометрический шейдер и в нем проверяем должен ли примитив быть выбран. Если да, то эмиттим вертекс точно в позиции (пикселе) что соответствует индексу примитива.
Идея слить все расчеты selection в геометричекий шейдер правильная, но в велосипедных способах вывода нет нужды, для этого давно есть штатное средство
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 17, 2020, 07:21 »

Как говорят, "может кому пригодится" Улыбающийся - конечно маловероятно. Но отписаться "чем дело кончилось" - хорошая привычка.

В конце-концов все сделал. используются только штатные средства и вся выборка полностью на GPU. Хотя не исключено что есть какие-то подводные камни о которых я не знаю. Как реализовано:

- для picking (выборки) я использую transforn feedback API совместно с геометрическим шейдером. В нем проверяю выбран ли примитив и если да, то записываю его индекс в выходной буфер. Важный момент: я (ошибочно) полагал что OpenGL "не умеет писать" (вывод только в текстуру). Это не так, писать он умел задолго до 3.3. Правда API там весьма задроченое, разобраться трудновато, но тем не менее.

- если нужно выбирать "только видимые" (не перекрытые другими) то дополнительно использую occlusion API, что также было в наличии задолго до 3.3. Правда приходится тюкать по 1 примитиву, ничего другого не нашел, но реализовать просто.

Наблюдаю интересный эффект. OpenGL - популярнейшая технология, "используют миллионы" Улыбающийся (что впрочем совсем не показатель квачества). Ну казалось бы для такой типовой задачи как "тыкать мышей" - уж должны быть накатаные решения! Здесь мы вправе рассчитывать и на open-sources или хотя бы какой-то sample code. Но я ничего такого не нашел, не видно было даже "куда копать". Да, популярное решение есть (кодировать цветом), но оно не устроило.

Т.е. выходит что "популярный уровень" (тонны тьюториалов перепечатывающих друг друга) - вовсе не "так уж хорошо". Мда..

Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.168 секунд. Запросов: 23.