Затенение Toon / Cel с переменной шириной линии?


15

Я вижу несколько общих подходов к затенению cel:

  1. Дублирование и увеличение модели с перевернутыми нормалями (не вариант для меня)
  2. Фильтр Собеля / фрагментный шейдер подходит к обнаружению края
  3. Трафаретный буфер подходит к обнаружению края
  4. Геометрические (или вершинные) шейдерные подходы, которые вычисляют грани и грани нормали

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

Что если мне не нужно пиксельное освещение на поверхностях моей местности? (И я, вероятно, не буду, поскольку я планирую использовать основанное на ячейке освещение / затенение на основе вершин или текстурной карты.) Тогда мне было бы лучше придерживаться подхода типа геометрии, или вместо этого пойти на подходе экранного пространства / фрагмента чтобы все было проще? Если так, то как бы получить «чернила» холмов внутри силуэта сетки, а не только контур всей сетки (без «чернильных» деталей внутри этого контура? (AKA наводит на мысль о контурах , складках ).

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

Что я хочу - переменная толщина линий с навязчивыми линиями внутри силуэта ...

введите описание изображения здесь

Чего я не хочу ...

введите описание изображения здесь


РЕДАКТИРОВАТЬ: Дальнейшие исследования обнаружили следующее ...

Поскольку у меня огромное количество вершин на местности, даже с учетом LoD на основе расстояния, ни подходы с перевернутыми нормалями, ни подход на основе геометрических шейдеров (даже с отбраковкой усеченного конуса) не были бы разумным вариантом из-за сложной вычислительной сложности, связанной с дублированием и масштабированием всех объектов. загруженные вершины.

Принимая во внимание, что мне не нужно освещение на пиксель в виде сплошного затенения на поверхностях местности, также становится менее разумным рассматривать любые подходы на основе нормалей к лицу - иначе требование для правильного освещения поверхности - так как они естественно, довольно дорого рассчитать. Однако верно то, что они дают наилучшую степень контроля; например, возможность затенять края с помощью «художественных» штрихов: красиво, но, опять же, не очень реально для чрезвычайно сложной игровой среды.

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

Это оставляет фрагменты шейдерных изображений-пространственных подходов. Сложность вычислений сводится к количеству фрагментов, а не к числу вершин (в моем случае это в 10-100 раз меньше операций, чем нужно было бы делать в геометрическом шейдере). Для этого требуется более одного прохода рендеринга, чтобы сгенерировать g-буфер (состоящий из обычного буфера и, возможно, буфера глубины), к которому мы можем применить фильтры разрывов (например, оператор Собеля). Глубина прерывистости - это то, что позволяет наводить контуры и складки. Единственное, что я могу сказать при таком подходе, - это невозможность обеспечить более точное управление шириной краев, хотя при использовании правильного алгоритма в фрагментном шейдере я уверен, что это возможно.

Таким образом, теперь вопрос становится более конкретным: как именно я получу переменную ширину ребер, особенно для внешнего силуэта, в фрагментном шейдере?


Изменение толщины линии является характерной чертой геометрического подхода. Не может эффективно получить это любым другим способом. Поскольку вы этого хотите, я не считаю пиксельные шейдеры «более эффективным методом»: количество искомых пикселей = (line_thickness * 2 + 1) ^ 2 - 1. Это в основном означает, что ваш шейдер после обработки будет намного (предположительно: 10x) медленнее, если макс. ширина линии равна 2. Просто отбросьте предварительную оценку и попробуйте геометрический шейдерный подход.
snake5

@ snake5 Честно говоря, вы предлагаете, чтобы в GS обновлялось 150 миллионов вершин за обновление рендеринга (около 25 миллионов при отбраковке представлений) в GS? Я на самом деле не покупаю это, но спасибо за вклад. Вернитесь к тому, что я сказал выше о количестве вершин и сложности. Даже с вашей 10-кратной фигурой фрагментный шейдер будет, по крайней мере, рисовать даже, и, вероятно, будет чертовски лучше.
инженер

25 миллионов вершин (линейное чтение / запись) против 23 миллионов образцов текстур (довольно плохо кэшированное чтение памяти + декомпрессия целевых данных рендеринга) @ 1280x720. Кстати, ограничение / уменьшение количества вершин намного проще. Особенно в наши дни, когда большие мониторы (1920x1080+) и мультимониторные установки становятся очень популярными.
snake5

как насчет того же алгоритма, который генерирует красные контуры, а затем уменьшать / увеличивать линии в зависимости от их глубины?
Ali1S232

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

Ответы:


4

Я решил пойти с подходом фрагментного шейдера через фильтрацию разрывов буфера глубины. Причины этого:

  1. Количество мировых вершин очень и очень велико из-за огромных расстояний обзора, даже с сеткой LoD;
  2. Я выполняю ряд других операций фрагментного шейдера, таких как размытие DoF, которые могут получить выгоду от тех же структур (коробчатая или гауссовая выборка / фильтрация) за один проход.

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


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

@Grieverheart Это принятый ответ, потому что метод, который я использую, прекрасно работает. Благодарю.
Инженер

0

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

Я изобрел алгоритм toonShader еще в 2000/2001 году, еще до того французского чувака, который создал это решение. Шахта была основана на фактической геометрии материалов. Тогда есть в основном два способа сделать это: 1. посмотреть на нормали, если нормали, две плоскости, соединенные с линией, обращены в сторону и к камере, визуализировать эту линию, вы можете использовать глубину, освещение и т. Д. В качестве сигналов для глубины линии. 2. Посмотрите на визуализированную геометрию (то есть после преобразования перспективы). Возьмите каждый сегмент линии, если вершины соединительных плоскостей находятся на одной стороне этого сегмента линии, вы визуализируете линию. Затем вы можете сделать то же самое для толщины линии, как в Метод 1. 3. Вы можете создавать комбинации из этих трех техник, но я упомянул первый, потому что вы указали огромное количество.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.