OpenGL: толстые и гладкие / не прерывистые линии * в 3D*

У меня есть 3D-CAD-приложение, для которого я использую библиотеку оболочки OpenGL (OpenSceneGraph). Для приложения я пытаюсь найти лучшую стратегию рендеринга толстых и плавных линий в 3D.

Под толстым и гладким я имею в виду:

  • толщина линии может быть больше, чем максимальное значение ширины линии OpenGL (кажется, 10.f на моей машине)
  • при составлении полилиний я хочу избежать появления "ломаных линий" (см. пример изображения ниже)

OpenGL <code>GL_LINE_STRIP_ADJACENCY</code>,</p><p>Я обнаружил, что есть много разных ресурсов о том, как визуализировать красивые линии и кривые в 2D. Самый простой подход, который не требует больших размышлений, состоит в том, чтобы визуализировать линию как набор квадратов (<code>GL_QUAD_STRIP</code>). Хорошая вещь об этом решении - то, что оно решает обе мои проблемы одновременно.</p><p>В качестве примера я также нашел эту <a href=симпатичную библиотеку, которая позволяет получить широкий диапазон линий и кривых. Для рендеринга используются треугольники.

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

Проблема этих двухмерных подходов состоит в том, что они являются двухмерными. Когда я меняю точку обзора, очевидно, что моя геометрия линий - это не линии, а двумерные "ленты", лежащие в определенных трехмерных плоскостях. И я хочу, чтобы они выглядели как трехмерные линии.

Размышляя о проблеме, я мог придумать только следующие подходы:

  1. Визуализируйте линию как набор двумерных квадратов (треугольников), а затем заставьте их всегда смотреть в камеру
  2. Используйте некоторую трехмерную форму, например, цилиндр, чтобы представить отрезок

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

РЕДАКТИРОВАТЬ: как указал пользователь @rickyviking, я не уточнил явно, что я собираюсь после 2D-вид (как в любом CAD-подобном приложении), который будет означать: толщина линий не зависит от того, как далеко / около камера находится от них.

ОБНОВЛЕНИЕ: спасибо за ответ @rickyviking, я выбрал направление для перемещения - геометрические шейдеры. У меня все еще нет полного решения, но я могу опубликовать окончательное обновление и минимальный код, когда будет достигнут результат, здесь.

4 ответа

Решение

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

Когда вы упоминаете цилиндры, они, безусловно, будут иметь "трехмерный эффект" (геометрии дальше, тоньше / меньше, чем геометрии ближе к точке обзора), но это не то, на что обычно похожи CAD-приложения.
Я полагаю, что вы ищете результат в 2D-виде, где ширина ваших линий не зависит от их расстояния от точки обзора.

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

Альтернативный и более эффективный подход - использовать технику "сплошного каркаса", здесь есть реализация от NVidia, которая использует геометрические шейдеры (вы можете найти несколько примеров их использования в OpenSceneGraph).
Другие подобные методы показаны здесь: https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader

В итоге я использовал геометрический шейдер, как было предложено в одном из ответов. Основная идея состояла в том, чтобы преобразовать каждый сегмент линии в треугольную полосу и убедиться, что она всегда обращена к камере, а толщина остается неизменной.

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

Вот несколько скриншотов результатов (зеленые линии нарисованы с помощью шейдеров, красные - с помощью GL_LINE_STRIP_ADJACENCY):

Пример той же толщины

пример большей толщины

Обратите внимание на промежутки между соседними отрезками красной линии по сравнению с зелеными.

Две кривые Безье (все нарисованы с использованием шейдеров):

Примеры кривой Безье

Я не слишком много знаю об этом, но одна из многих интересных вещей в SDK NVIDIA "Path Rendering" (который был просто еще одной из тех замечательных 2D-библиотек, о которых вы говорите) заключалась в том, что немного усилий для взаимодействия с 3D. Смотрите "Эврика: 3D рендеринг пути!" раздел в этом техническом описании.

Раньше говорили о том, что это стандартное (не зависящее от производителя) расширение OpenGL, но я не уверен, что это когда-либо происходило.

Я раньше использовал цилиндры, но это было приложение, которое нуждалось в реальных реальных размерах, разных размерах в одной строке и даже изменении цвета.

Другие вопросы по тегам