EDIT: Будь ласка, дивіться мою іншу відповідь з конкретним рішенням.
Цю точну проблему я вирішив понад рік тому для магістерської роботи. У статті Valve вони показують, що ви можете І два поля відстані, щоб досягти цього, що працює, поки у вас є лише один опуклий кут. Для увігнутих кутів вам також потрібна операція АБО. Цей хлопець фактично розробив якусь незрозумілу систему для перемикання між двома операціями за допомогою чотирьох каналів текстури.
Однак є набагато простіша операція, яка може полегшити І ІЛИ АБО, залежно від ситуації, і це головна ідея моєї тези: медіана трьох . Отже, ви використовуєте рівно три канали (ідеально підходять для RGB), які є повністю взаємозамінними, і комбінуєте їх за допомогою медіанної операції (виберіть середнє значення з трьох).
Для розміщення антизбудження ми працюємо не просто з булевими, а значеннями з плаваючою точкою, і операція AND стає мінімальною, а АБО стає максимумом двох значень. Медіана трьох може дійсно робити і те й інше: якщо a < b , for ( 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 та монохромною.