РЕДАКТИРОВАТЬ: Пожалуйста, посмотрите мой другой ответ с конкретным решением.
Я действительно решил эту проблему более года назад для моей магистерской диссертации. В документе Valve они показывают, что вы можете И два поля расстояния для достижения этого, что работает, пока у вас есть только один выпуклый угол. Для вогнутых углов вам также понадобится операция ИЛИ. Этот парень на самом деле разработал какую-то непонятную систему для переключения между двумя операциями, используя четыре текстурных канала.
Однако есть намного более простая операция, которая может облегчить И и ИЛИ в зависимости от ситуации, и это главная идея моего тезиса: медиана трех . Таким образом, в основном вы используете ровно три канала (идеально для RGB), которые полностью взаимозаменяемы, и объединяете их, используя медианную операцию (выберите среднее значение из трех).
Чтобы приспособиться к сглаживанию, мы работаем не только с логическими значениями, а со значениями с плавающей запятой, и операция И становится минимальной, а ИЛИ становится максимальной двух значений. Медиана трех может действительно сделать и то и другое: если a < b , для ( a , a , b ) медиана является минимумом, а для ( a , b , b ) это максимум.
Процесс рендеринга все еще чрезвычайно прост. Весь фрагментный шейдер, включая сглаживание, может выглядеть примерно так:
int main() {
// Bilinear sampling of the distance field
vec3 s = texture2D(sdf, p).rgb;
// Acquire the signed distance
float d = median(s.r, s.g, s.b) - 0.5;
// Weight between inside and outside (anti-aliasing)
float w = clamp(d/fwidth(d) + 0.5, 0.0, 1.0);
// Combining the background and foreground color
gl_FragColor = mix(outsideColor, insideColor, w);
}
Таким образом, единственное отличие от оригинального метода - вычисление медианы сразу после выборки текстуры. Вы должны будете реализовать функцию медианы, которая может быть сделана всего за 4 минуты / макс .
Теперь, конечно, вопрос в том, как мне построить такое трехканальное поле расстояния?И это сложная часть. Самый очевидный подход, который я использовал в начале, состоял в том, чтобы выполнить разложение входной фигуры / глифа на три компонента, а затем сгенерировать обычное поле расстояния из каждого. Правила для этого разложения не так сложны. Во-первых, область с как минимум 2 из 3 каналов находится внутри. Затем, если вы представляете это как цветовые каналы RGB, выпуклые углы должны быть сделаны из вторичного цвета, и его два основных компонента продолжаются наружу. Вогнутые углы являются обратными: два вторичных цвета заключают в себе свой основной основной цвет, а клин между тем, где оба края продолжаются внутрь, является белым. Я также обнаружил, что некоторые отступы необходимы там, где два основных или два вторичных цвета в противном случае соприкасались бы, чтобы избежать артефактов (например, в середине штриха "N").
Следующее изображение является примером декомпозиции, сгенерированной программой из моей диссертации:
Этот подход, однако, имеет некоторые недостатки. Одним из них является то, что специальные эффекты, такие как контуры и тени, больше не будут работать правильно. К счастью, я также придумал второй, гораздо более элегантный метод, который напрямую генерирует поля расстояний и даже поддерживает все графические эффекты. Это также включено в мою диссертацию и так же старше года. Я не буду сейчас вдаваться в подробности, потому что сейчас я пишу статью, в которой подробно описывается этот второй метод, но я опубликую его здесь, как только он будет закончен.
Во всяком случае, вот пример разницы в качестве. Разрешение текстуры одинаково на каждом изображении, но в левом используется обычная текстура, в среднем - обычное поле расстояния, а в правом - мое трехканальное поле расстояния. Снижение производительности - это только разница между дискретизацией текстуры RGB и монохромной.