EDIT: Vedi la mia altra risposta con una soluzione concreta.
In realtà ho risolto esattamente questo problema più di un anno fa per la tesi del mio maestro. Nel documento Valve, mostrano che puoi E due campi di distanza per raggiungere questo obiettivo, che funziona fintanto che hai solo un angolo convesso. Per gli angoli concavi, è necessaria anche l'operazione OR. Questo ragazzo in realtà ha sviluppato un sistema oscuro per passare tra le due operazioni usando quattro canali di trama.
Tuttavia, esiste un'operazione molto più semplice che può facilitare sia AND che OR a seconda della situazione, e questa è l'idea principale della mia tesi: la mediana di tre . Quindi, fondamentalmente, usi esattamente tre canali (ideali per RGB), che sono completamente intercambiabili, e combinali usando l'operazione mediana (scegli il valore medio tra i tre).
Per soddisfare l'antialiasing, non lavoriamo solo con valori booleani, ma a virgola mobile e l'operazione AND diventa il minimo e OR diventa il massimo di due valori. La mediana di tre può effettivamente fare entrambe le cose: se a < b , per ( a , a , b ), la mediana è il minimo e per ( a , b , b ), è il massimo.
Il processo di rendering è ancora estremamente semplice. L'intero shader di frammenti, incluso l'antialiasing, può assomigliare a questo:
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);
}
Quindi l'unica differenza rispetto al metodo originale è calcolare la mediana subito dopo aver campionato la trama. Dovrai tuttavia implementare la funzione mediana, che può essere eseguita con solo 4 min / max operazioni .
Ora, naturalmente, la domanda è: come posso costruire un campo di distanza così a tre canali?E questa è la parte difficile. L'approccio più ovvio che ho adottato all'inizio è stato quello di eseguire una decomposizione della forma / glifo di input in tre componenti e quindi generare un campo di distanza convenzionale da ciascuno di essi. Le regole per questa scomposizione non sono così complicate. Innanzitutto, l'area con almeno 2 canali su 3 attivi è l'interno. Quindi, se lo immagini come canali di colore RGB, gli angoli convessi devono essere fatti di un colore secondario e i suoi due componenti primari continuano verso l'esterno. Gli angoli concavi sono l'inverso: due colori secondari racchiudono il loro colore primario comune e il cuneo tra il punto in cui entrambi i bordi continuano verso l'interno è bianco. Ho anche scoperto che è necessaria una certa imbottitura in cui due colori primari o due secondari toccherebbero altrimenti per evitare artefatti (ad esempio, nel tratto centrale della "N"
L'immagine seguente è un esempio di scomposizione generata dal programma dalla mia tesi:
Questo approccio presenta tuttavia alcuni inconvenienti. Uno di questi è che gli effetti speciali, come i contorni e le ombre, non funzioneranno più correttamente. Fortunatamente, ho anche escogitato un secondo metodo molto più elegante, che genera direttamente i campi di distanza e supporta persino tutti gli effetti grafici. È anche incluso nella mia tesi e quindi ha anche più di un anno. Non fornirò ulteriori dettagli in questo momento, perché attualmente sto scrivendo un documento che descrive in dettaglio questa seconda tecnica, ma la posterò non appena sarà finita.
Ad ogni modo, ecco un esempio della differenza di qualità. La risoluzione della trama è la stessa in ogni immagine, ma quella sinistra usa una trama normale, quella centrale usa un campo di distanza ordinario e quella destra usa il mio campo di distanza a tre canali. L'overhead delle prestazioni è solo la differenza tra il campionamento di una trama RGB rispetto a una monocromatica.