Tomando o seu exemplo, você tem uma função passo da distância, que produz uma aresta perfeitamente rígida (alias). Uma maneira simples de suavizar o círculo seria transformá-lo em um limiar suave, como:
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);
Aqui eu usei uma rampa linear fixa para uma função de limite suave, mas você também pode usar smoothstep
ou outra coisa. O + 0.5
é centralizar a rampa na localização matemática da aresta. De qualquer forma, o importante é que essa função mude suavemente de outsideColor
para insideColor
algumas distâncias; portanto, se você escolher thresholdWidth
adequadamente, obterá uma vantagem de aparência antialias.
Mas como você deve escolher thresholdWidth
? Se for muito pequeno, você receberá o alias novamente e, se for muito grande, a borda ficará muito embaçada. Além disso, geralmente dependerá da posição da câmera: se dist
for medido em unidades do espaço mundial ou do espaço da textura, um thresholdWidth
que funcione para uma posição da câmera estará errado para outra.
Aqui é onde os derivados do espaço da tela entram (sim, eles são ddx
e ddy
funcionam como você adivinhou). Ao calcular o comprimento do gradiente, dist
você pode ter uma idéia da rapidez com que está mudando no espaço da tela e usá-lo para estimar thresholdWidth
, como:
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
Você ainda tem um valor que pode ajustar para obter o nível desejado de suavidade, mas agora deve obter resultados consistentes, independentemente da posição da câmera.
derivX
ederivY
realmente representam.derivX
ederivY
são apenas (aproximações) as derivadas parciais de qualquer expressão na qual você passaddx
eddy
, com relação ao espaço na tela x e y. Se você não estudou cálculo, esse é um tópico maior do que posso explicar aqui. :)dFdx
/ emdFdy
vez deddx
/ddy
.