En prenant votre exemple, vous avez une fonction de pas de la distance, ce qui produit un bord parfaitement dur (aliasé). Un moyen simple d'antialiaser le cercle serait de transformer cela en un seuil souple, comme:
float distFromEdge = 1.0 - dist; // positive when inside the circle
float thresholdWidth = 0.01; // a constant you'd tune to get the right level of softness
float antialiasedCircle = saturate((distFromEdge / thresholdWidth) + 0.5);
return lerp(outsideColor, insideColor, antialiasedCircle);
Ici, j'ai utilisé une rampe linéaire serrée pour une fonction de seuil doux, mais vous pouvez également utiliser smoothstep
ou autre chose. Il + 0.5
s'agit de centrer la rampe sur l'emplacement mathématique du bord. Quoi qu'il en soit, le point est que cette fonction change en douceur de outsideColor
la insideColor
sur une plage de distances, donc si vous prenez thresholdWidth
correctement , vous aurez un avantage crénelées prospectifs.
Mais comment choisir thresholdWidth
? S'il est trop petit, vous obtiendrez à nouveau un alias, et s'il est trop grand, le bord sera trop flou. De plus, cela dépendra généralement de la position de la caméra: si elle dist
est mesurée en unités de l'espace-monde ou de l'espace-texture, alors une thresholdWidth
qui fonctionne pour une position de caméra sera fausse pour une autre.
Voici où les dérivés de l'espace d'écran entrent en jeu (oui, ce sont les fonctions ddx
et ddy
comme vous l'avez deviné). En calculant la longueur du gradient de dist
vous pouvez vous faire une idée de la vitesse à laquelle il change dans l'espace de l'écran et l'utiliser pour estimer thresholdWidth
, comme:
float derivX = ddx(distFromEdge);
float derivY = ddy(distFromEdge);
float gradientLength = length(float2(derivX, derivY));
float thresholdWidth = 2.0 * gradientLength; // the 2.0 is a constant you can tune
Vous avez toujours une valeur que vous pouvez régler pour obtenir le niveau de douceur souhaité, mais maintenant vous devriez obtenir des résultats cohérents quelle que soit la position de la caméra.
derivX
etderivY
représentent en réalité.