Расстояние от экрана до линейной полосы в GLSL

При рендеринге линейной полосы, как я могу получить расстояние фрагмента до начальной точки всей полосы вдоль линии в пикселях?

При рендеринге одного отрезка прямой между двумя точками в 3D, расстояние между этими двумя точками в пространстве экрана - это просто евклидово расстояние между их 2D проекциями. Если я рендеринг этого сегмента, я могу интерполировать (квалификатор макета неопределяемый в GLSL) расстояние экрана от начальной точки вдоль линии для каждого фрагмента.

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

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

Что я сейчас делаю:

  • проецировать каждую точку линии заранее на CPU
  • рассчитать длину всех проецируемых отрезков в пикселях
  • сохранить длины в буфере как атрибут вершины (вершина 0 имеет расстояние 0, вершина 1 имеет длину сегмента 0->1, вершина 2 имеет длину 0->1 + 1->2, ...)
  • в геометрическом шейдере создайте отрезки и используйте расстояния, рассчитанные на CPU
  • интерполировать значения без коррекции перспективы для каждого фрагмента

Это работает, но должен быть лучший способ сделать это. Невозможно проецировать несколько сотен или тысяч точек линий на ЦП в каждом кадре. Есть ли умный способ рассчитать это в геометрическом шейдере? То, что у меня есть, это позиция в мировом пространстве начальной и конечной точек текущего отрезка линии, у меня есть расстояние в мировом пространстве обеих точек до начальной точки линейной полосы вдоль линии (опять же атрибут вершины 0, 0->1, 0->1 + 1->2, ...) и я могу предоставить любые другие однородные данные о линейной полосе (общая длина в мировых единицах пространства, количество сегментов, ...).

Редактировать: я не хочу вычислять евклидово расстояние до начальной точки линейной полосы, но расстояние по всей линии, то есть сумму длин всех спроецированных отрезков линии до текущего фрагмента.

2 ответа

Решение

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

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

Форрестер Коул и Адам Финкельштейн. Два быстрых метода для качественной линейной видимости. Сделки IEEE по визуализации и компьютерной графике 16(5), февраль 2010.

которая имеет дело с этой самой проблемой. Решение похоже на то, что уже предложено derhass. Коул и Финкельштейн используют сегментный атлас, который они вычисляют за кадр в GPU. Он включает в себя список всех проецируемых точек линии (среди других атрибутов, таких как видимость), чтобы отслеживать положение вдоль линии в каждом фрагменте. Этот сегментный атлас вычисляется в фрейм-буфере, поскольку документ (черновик) датируется 2009 годом. Реализация одного и того же метода в вычислительном шейдере и сохранение результатов в буфере кажется подходящим способом.

Я вижу два пути:

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

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

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