In Ihrem Beispiel haben Sie eine Schrittfunktion der Entfernung, die eine perfekt harte (Alias-) Kante erzeugt. Eine einfache Möglichkeit, den Kreis zu antialiasieren, besteht darin, ihn in eine weiche Schwelle umzuwandeln, wie z.
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);
Hier habe ich eine geklemmte lineare Rampe für eine Soft-Threshold-Funktion verwendet, aber Sie könnten auch smoothstep
oder etwas anderes verwenden. Das + 0.5
ist, um die Rampe auf der mathematischen Position der Kante zu zentrieren. Der Punkt ist jedenfalls, dass sich diese Funktion reibungslos von outsideColor
zu insideColor
über einen bestimmten Bereich von Entfernungen ändert. Wenn Sie also die thresholdWidth
richtige Auswahl treffen, erhalten Sie eine antialias-aussehende Kante.
Aber wie solltest du wählen thresholdWidth
? Wenn es zu klein ist, erhalten Sie erneut ein Aliasing, und wenn es zu groß ist, ist die Kante übermäßig verschwommen. Darüber hinaus hängt es im Allgemeinen von der Kameraposition ab: Wenn dist
es in Weltraum- oder Texturraumeinheiten gemessen wird, ist eine Funktion thresholdWidth
, die für eine Kameraposition funktioniert, für eine andere falsch.
Hier kommen die Screen-Space-Ableitungen ins Spiel (ja, sie sind die ddx
und ddy
funktionieren, wie Sie vermutet haben). Indem Sie die Länge des Gradienten berechnen dist
, können Sie eine Vorstellung davon bekommen, wie schnell sich der Bildschirmbereich ändert, und diese verwenden, um Folgendes zu schätzen thresholdWidth
:
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
Sie haben immer noch einen Wert, den Sie einstellen können, um den gewünschten Weichheitsgrad zu erzielen. Jetzt sollten Sie jedoch unabhängig von der Kameraposition konsistente Ergebnisse erzielen.
derivX
undderivY
tatsächlich repräsentieren.