Я вижу несколько общих подходов к затенению cel:
- Дублирование и увеличение модели с перевернутыми нормалями (не вариант для меня)
- Фильтр Собеля / фрагментный шейдер подходит к обнаружению края
- Трафаретный буфер подходит к обнаружению края
- Геометрические (или вершинные) шейдерные подходы, которые вычисляют грани и грани нормали
Правильно ли я считаю, что геометрический подход дает наибольший контроль над освещением и толщиной линии, например. для местности, где вы можете увидеть линию силуэта холма, постепенно сливающегося в равнину?
Что если мне не нужно пиксельное освещение на поверхностях моей местности? (И я, вероятно, не буду, поскольку я планирую использовать основанное на ячейке освещение / затенение на основе вершин или текстурной карты.) Тогда мне было бы лучше придерживаться подхода типа геометрии, или вместо этого пойти на подходе экранного пространства / фрагмента чтобы все было проще? Если так, то как бы получить «чернила» холмов внутри силуэта сетки, а не только контур всей сетки (без «чернильных» деталей внутри этого контура? (AKA наводит на мысль о контурах , складках ).
Наконец, возможно ли дешево эмулировать подход с перевернутыми нормалями, используя геометрический шейдер? Меня беспокоит то, что я могу точно продублировать каждую вершину и масштабировать их соответствующим образом, но как бы я подошел к переворачиванию нормалей и отдельной окраске в фрагментном шейдере?
Что я хочу - переменная толщина линий с навязчивыми линиями внутри силуэта ...
Чего я не хочу ...
РЕДАКТИРОВАТЬ: Дальнейшие исследования обнаружили следующее ...
Поскольку у меня огромное количество вершин на местности, даже с учетом LoD на основе расстояния, ни подходы с перевернутыми нормалями, ни подход на основе геометрических шейдеров (даже с отбраковкой усеченного конуса) не были бы разумным вариантом из-за сложной вычислительной сложности, связанной с дублированием и масштабированием всех объектов. загруженные вершины.
Принимая во внимание, что мне не нужно освещение на пиксель в виде сплошного затенения на поверхностях местности, также становится менее разумным рассматривать любые подходы на основе нормалей к лицу - иначе требование для правильного освещения поверхности - так как они естественно, довольно дорого рассчитать. Однако верно то, что они дают наилучшую степень контроля; например, возможность затенять края с помощью «художественных» штрихов: красиво, но, опять же, не очень реально для чрезвычайно сложной игровой среды.
Я бы предпочел избегать трафаретных буферов, так как предпочел бы выполнять всю работу в шейдерах. (Приведенный выше пример с красным контуром был сделан с помощью трафаретного буфера - старая школа.)
Это оставляет фрагменты шейдерных изображений-пространственных подходов. Сложность вычислений сводится к количеству фрагментов, а не к числу вершин (в моем случае это в 10-100 раз меньше операций, чем нужно было бы делать в геометрическом шейдере). Для этого требуется более одного прохода рендеринга, чтобы сгенерировать g-буфер (состоящий из обычного буфера и, возможно, буфера глубины), к которому мы можем применить фильтры разрывов (например, оператор Собеля). Глубина прерывистости - это то, что позволяет наводить контуры и складки. Единственное, что я могу сказать при таком подходе, - это невозможность обеспечить более точное управление шириной краев, хотя при использовании правильного алгоритма в фрагментном шейдере я уверен, что это возможно.
Таким образом, теперь вопрос становится более конкретным: как именно я получу переменную ширину ребер, особенно для внешнего силуэта, в фрагментном шейдере?
источник
Ответы:
Я решил пойти с подходом фрагментного шейдера через фильтрацию разрывов буфера глубины. Причины этого:
Протестировав его, я бы сказал, что в будущих проектах вместо этого я выберу подход на основе геометрии по причинам сложности. Причина в том, что (как другие предложили в комментариях) подходы к фрагментному шейдеру для обнаружения края могут быть вычислительно интенсивными, особенно с реализациями DoF, где радиус радиуса путаницы и, следовательно, количество выборок на фрагмент могут быть довольно высокими. К счастью, это меньше заботит контурные шейдеры.
источник
На самом деле есть очень простое общее решение, если вы можете использовать эффект после. Самое замечательное, что не имеет значения, насколько высок ваш счетчик. Визуализируйте карту глубины в оттенках серого, затем создайте точку нужного цвета линии, когда контраст между двумя соседними пикселями выше порогового значения. Вы можете увеличить точку в зависимости от контраста или уровня освещенности изображения, которое вы отрисовали.
Я изобрел алгоритм toonShader еще в 2000/2001 году, еще до того французского чувака, который создал это решение. Шахта была основана на фактической геометрии материалов. Тогда есть в основном два способа сделать это: 1. посмотреть на нормали, если нормали, две плоскости, соединенные с линией, обращены в сторону и к камере, визуализировать эту линию, вы можете использовать глубину, освещение и т. Д. В качестве сигналов для глубины линии. 2. Посмотрите на визуализированную геометрию (то есть после преобразования перспективы). Возьмите каждый сегмент линии, если вершины соединительных плоскостей находятся на одной стороне этого сегмента линии, вы визуализируете линию. Затем вы можете сделать то же самое для толщины линии, как в Метод 1. 3. Вы можете создавать комбинации из этих трех техник, но я упомянул первый, потому что вы указали огромное количество.
источник