Линия для Direct3D толщина
Как изменить толщину линий при рисовании списков линий с помощью Direct3D?
этот пост говорит, что ширина линии не поддерживается и приводится решение. Другие варианты?
пока мы находимся в этой теме, шейдеры позволяют рисовать линии с помощью шаблонов тире?
4 ответов
вы можете использовать геометрический шейдер, который будет принимать в качестве входного сегмента вашей линии и выводить квадроцикл (треугольную полосу из двух треугольников), чтобы ширина квадроцикла была постоянной в пространстве экрана и соответствовала толщине линии желания. Он отлично работает (для реализации его в 3D-движке CAD).
если геометрический шейдер не является опцией, обходным путем может быть использование вершинного шейдера, но для этого потребуется некоторая повторная работа вашего VB. Имейте в виду, что против должны имейте знание сегмента линии в целом, поэтому вы в конечном итоге сохраните p и p+1 для каждого из ваших элементов VB, а также стоимость дублирования индексов/вершин (в зависимости от используемой топологии и если вы визуализируете свою линию как индексированный примитив или нет).
если производительность не является проблемой, выполнение расширения на CPU, возможно, путь.
EDIT:
о шаблоны: вы также можете использовать шейдер геометрии для эмуляции glLineStipple
поведение.
Если у вас есть GL_LINES
топология, то есть изолированные линии, шаблон перезапускается на каждом новом сегменте линии. Поэтому вам просто нужно вычислить в геометрическом шейдере горизонтальный старт экрана (или вертикальный старт, в зависимости от ориентации) вашего сегмента линии и передать эту дополнительную информацию в пиксельный шейдер. Затем пиксельный шейдер будет отвечать за отбрасывание фрагментов в соответствии с фактор и шаблон значения (целое число DirectX 10/11 и Побитовые инструкции делают его легким).
опять же это хорошо работает, и вы можете объединить его с эмулированными линиями ширины (с первой техникой выше).
теперь, если у вас есть GL_LINE_STRIP
топология, шаблон перезапускается при каждом новом примитиве (так для каждого нового вызова draw). Ситуация становится немного сложнее, так как вам нужно знать количество пикселей, которые были визуализированы ранее, и это для каждого сегмента линии.
вы можете добиться что при рендеринге линейной полосы во временном VB с использованием функции потока DirectX 10 (каждый элемент этого VB соответствует длине экрана каждого сегмента). Затем вам нужно сделать параллельную сумму префикса (aka Scan) этого VB (для накопления значений длины каждого сегмента линии).
наконец, вы рендеринг вашей линии полосы, как для GL_LINES
но используйте эту дополнительную информацию сканирования VB в PS.
толщина линии не только не поддерживается Direct3D,но и не поддерживается ни одним из существующих GPU. Нет GPU, о котором я знаю, который может даже рисовать правильные линии вообще (все они поддельные линии, используя вырожденные полигоны - то есть вторая и третья вершины находятся в одном и том же положении, поэтому треугольник по существу сжимается до одной линии).
хотя можно установить ширину линии в OpenGL, драйвер OpenGL создает экструдированные квадроциклы (которые не являются поддерживается и текущим GPU, и эмулируется с использованием двух треугольников для каждого квадрата), чтобы нарисовать "линии" на экране.
поэтому, вероятно, нет никакого способа создать экструдированные квадроциклы для этой цели. Есть несколько способов добиться этого, как объяснил Стрингер Белл в своем ответе.
самый простой способ, который работает для меня, - создать буфер вершин, содержащий каждую вершину дважды, с нормалями, указывающими "вправо" или "влево", в зависимости от того, являются ли они правыми или левыми край линии. Затем очень простой вершинный шейдер может выполнять экструзию (изменяя положение вершины на кратное ее нормальному вектору). Таким образом, вы можете быстро изменить ширину линии, не пересчитывая геометрию на CPU. Это может быть полезно, если вы хотите изменить ширину линии в зависимости от размера объекта или расстояния.
Что касается вашего вопроса о шаблоне тире (stippling), лучше всего, вероятно, визуализировать линию в виде тонкого квадрата и применить к ней текстуру в пиксельном шейдере, где текстура содержит ваш шаблон тире. Вам нужно будет установить режим адреса сэмплера для обертывания, что-то вроде:
SamplerState wrapTriLinear {
AddressU = WRAP;
AddressV = WRAP;
}