Толщина линии Direct3D - PullRequest
       35

Толщина линии Direct3D

14 голосов
/ 17 февраля 2010

Как изменить толщину линий при рисовании списков линий с использованием Direct3D?

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

Пока мы занимаемся этой темой, позволяют ли шейдеры рисовать линии с помощью штриховых рисунков?

Ответы [ 4 ]

16 голосов
/ 17 февраля 2010

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

Если геометрический шейдер не является опцией, можно обойти это путем использования вершинного шейдера, но это потребует некоторой доработки вашегоVB.Имейте в виду, что VS должен знать о линейном сегменте в целом, так что вы в конечном итоге сохраните p и p + 1 для каждого из ваших элементов VB плюс стоимость дублирования индексов / вершин (в зависимости от используемой топологии иесли вы представляете свою строку как индексированный примитив или нет).

Если производительность не является проблемой, возможно, вам нужно выполнить расширение на ЦП.

РЕДАКТИРОВАТЬ:

О шаблонах штрихов : вы также можете использовать геометрический шейдер для эмуляции поведения glLineStipple.Если у вас топология GL_LINES, то есть изолированные линии, шаблон перезапускается на каждом новом сегменте линии.Таким образом, вам просто нужно вычислить в геометрическом шейдере горизонтальное начало пространства экрана (или вертикальное начало, в зависимости от ориентации) сегмента линии и передать эту дополнительную информацию в пиксельный шейдер.Затем пиксельный шейдер будет отвечать за удаление фрагментов в соответствии со значениями factor и pattern (инструкции DirectX 10/11 Integer и Bitwise делают это простым).

Сноваэто работает хорошо, и вы можете комбинировать его с эмулируемыми линиями ширины (с первой вышеупомянутой техникой).

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

Этого можно добиться с помощью рендеринга линейного отрезка во временной области.VB с использованием функции потоковой передачи DirectX 10 (каждый элемент этого VB соответствует длине экранного пространства каждого сегмента).Затем вы должны выполнить Parallel Prefix Sum (aka Scan) этого VB (для накопления значений длины каждого сегмента линии).

Наконец, вы визуализируете линейку как для GL_LINES, но используете этот дополнительный Scan VBинформация в ПС.

15 голосов
/ 18 февраля 2010

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

Хотя можно установить ширину линии в OpenGL, драйвер OpenGL создает вытянутые четырехугольники (которые также не поддерживаются и текущим графическим процессором, и эмулируется с использованием двух треугольников для каждого четырехугольника) для рисования «линий» на экране. .

Так что, вероятно, нет никакого способа создать экструдированные четырехугольники для этой цели. Как объяснил Стрингер Белл в своем ответе, есть несколько способов достичь этого.

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

0 голосов
/ 24 мая 2013

Что касается вопроса о пунктирном узоре (пунктир), вам лучше всего сделать линию в виде тонкого квадрата и наложить на нее текстуру в пиксельном шейдере, где текстура содержит ваш штрих-рисунок. Вам нужно установить режим адресации сэмплера для переноса, что-то вроде:

SamplerState wrapTriLinear {
    AddressU = WRAP;
    AddressV = WRAP;
}
...