Не хотелось поднимать старый топик)
Год назад я искал наиболее подходящий алгоритм выбора объектов мышью в 3D для своей утилиты, и, наткнувшись на эту тему твердо решил не использовать для этих целей z-буфер. По иронии судьбы, в данный момент в моей программе используется именно он. В сравнении с другими методами (буфер выбора, буфер цвета, пересечение луча с треугольником), я нахожу его наиболее простым в исполнении и при этом достаточно быстрым.
Суть та же, что в постах топикстартера:
1. Очистить буфер глубины.
2. Цикл по объектам:
2.1 Рисуем i-й объект.
2.2 glFinish().
2.3 Если значение в z-буфере в элементе под курсором изменилось, значит текущий объект под мышкой и расположен к ней ближе всех уже нарисованных.
По поводу glFinish()
На самом деле, вызов glFinish() здесь даже лишний и перед glReadPixels() не требуется, если верить документации:
Однако, на форумах поговаривают, что не все видеокарты адекватно воспринимают glReadPixels() без предшествующего вызова glFinish(), и для надежности последний лучше оставить.
По поводу производительности
1. Отключить освещение, использовать более простую геометрию для отрисовки в функции выбора, если это возможно.
2. Т. к. нас интересует только буфер глубины, имеет смысл отключить рисование в буфер цвета:
либо glDrawBuffer(Gl.GL_NONE); либо glColorMask(0, 0, 0, 0); При отрисовке сцены не забыть вернуть все на место: glDrawBuffer(Gl.GL_BACK); glColorMask(1, 1, 1, 1);
3. Преобразовать матрицу GL_PROJECTION так, чтобы видимый объем уменьшился до призмы с основание 1х1 пиксель под курсором. Тестом отреза оставить отрисовку только в регионе 1х1 пиксель.
4. В принципе, этого должно быть достаточно для приемлемой скорости работы (мне, например, хватает :) ). Если нет - есть совсем извращенный вариант: для каждого объекта хранить значение в отдельном элементе буфера глубины; тогда за один вызов glReadPixels() можно будет получить значения глубины для всех объектов сразу.
Тема в архиве.