2010-02-17 2 views
13

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

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

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

ответ

14

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

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

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

EDIT:

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

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

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

Вы можете добиться этого с помощью рендеринга вашей линейной полосы во временном VB, используя функциональность Stream-out DirectX 10 (каждый элемент этого VB соответствует длине экрана каждого сегмента). Затем вам нужно выполнить Параллельный префикс Sum (aka Scan) этого VB (для накопления значений длины каждого сегмента строки).

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

13

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

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

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

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

+0

Это интересное решение. Достигли ли вы достижения тех же результатов, что и с вызовом glLineWidth (по одному пикселю)? – Stringer

+0

Я не проверял его на пиксель, но для неструктурированных, сглаженных линий результаты должны быть достаточно похожи. Использование текстуры (например, для эмуляции шаблонов шаблонов OpenGL), несомненно, приведет вас в мир боли, с нелинейной интерполяцией координат текстуры (которые NVidia Quadros обрабатывают невероятно плохо, даже по сравнению с большей частью идентичной частью Geforce). Шейдеру необходимо выполнить много дополнительной работы, чтобы получить текс-кодеры. – Pepor

+0

Вы можете попробовать это самостоятельно, просто используйте какую-то «длину линии в пикселях экрана» для координат текстуры и нарисуйте линию (линии) с текстурой, на которой есть шаблон узора. Вы будете удивлены тем, насколько неравномерен шаблон. По крайней мере, я был. ;-) – Pepor

0

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

SamplerState wrapTriLinear { 
    AddressU = WRAP; 
    AddressV = WRAP; 
} 
Смежные вопросы