Кривые уровня на поверхности в OpenGL - PullRequest
0 голосов
/ 12 июня 2018

У меня есть функция f, определенная в сетке треугольника, то есть для каждой вершины у меня есть связанный номер.Например, f может быть геодезическим расстоянием в сетке, то есть f (x) = d (a, x), вычисленным для каждой точки в сетке от определенной фиксированной точки a.Ясно, что легко «нарисовать» эту функцию на поверхности, просто нормализуя значения f и сопоставив их с цветами на узлах сетки.

Но что, если я хочу нарисовать изолинии (также называемый контурными линиями или изоклинами) на поверхности?

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

Для справки, я использую Python OpenGL.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Допустим, вы хотите нарисовать контуры (изолинии), чья координата Z кратна ci (для «интервала контура»).например, для ci=5 допустимыми значениями являются 25, 30, 35 и т. д.
Треугольник может не иметь ни одного, одного или нескольких контуров, пересекающих его.Я не беспокоюсь о линиях.Я использую точки, я проверяю каждый фрагмент в фрагментном шейдере.

Первая цель - вернуть мировые координаты фрагмента в фрагментном шейдере.
Фрагментный шейдер получает gl_FragCoord с {x,y,z} в экранных координатах.Или в вершинном шейдере вы можете передать варьирующийся с z.Прочитайте этот вопрос & 1014 *, чтобы узнать, как можно выполнить обратное преобразование.

Теперь у вас есть z в мировых координатах, пришло время определить, принадлежит ли он контуруили нет:

float maxErr = 0.0001;
float dif = abs(z - (ci * floor(z/ci)));
if ( dif > maxErr )
    color = triangleColor;
else
    color = contourColor;

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

0 голосов
/ 12 июня 2018

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

Самый простой -чтобы использовать один проход рендеринга, используйте что-то подобное во фрагменте:

float x;
x = (value/10.0)+0.5; // 10 is distance of value you want the lines to render
x = x-floor(x);   // x = value mod distance
if (abs(x-0.5)>0.001) discard; // do not render fragments too far from your line

код просто решает, находитесь ли вы очень близко к каждому расстоянию = 10 от значения, и отбрасываете любые фрагменты, которые не являются таковыми.Однако толщина линий / кривых может варьироваться в зависимости от плотности значений и распределения размера треугольника.Вы должны правильно установить константы (distance=10,threshold=0.001), чтобы сделать эту работу.

Этот Подсветка поверхности анимированной сетки GLSL использует очень похожую технику, кроме отбрасывания, поскольку материал там непрерывный.

Более точный вариант - использовать тот же принцип в 2-х проходном рендере.Где вы представляете свою ценность как цвет в некоторой текстуре в первом проходе.И затем за секунду для каждого фрагмента вы сканируете текстуру вокруг и находите ближайшую позицию отображаемого значения, а затем на основе расстояния до него либо визуализируете, либо нет.Это обеспечивает точную толщину линии, несмотря ни на что.Но для этого значение должно содержать конкретные значения рендеринга.Этот Как реализовать эффект 2D лучевого освещения в GLSL может помочь, так как он также сканирует текстуру во всех направлениях (но для разных целей).

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

...