Mengambil contoh Anda, Anda memiliki fungsi langkah jarak, yang menghasilkan tepi yang sangat keras (alias). Cara sederhana untuk antialias lingkaran adalah mengubahnya menjadi ambang lunak, seperti:
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);
Di sini saya menggunakan jalan linear dijepit untuk fungsi ambang lunak, tetapi Anda juga bisa menggunakan smoothstepatau sesuatu yang lain. The + 0.5adalah untuk pusat jalan di lokasi matematika dari tepi. Pokoknya, intinya adalah bahwa fungsi ini dengan lancar berubah dari outsideColorke insideColorbeberapa rentang jarak, jadi jika Anda memilih dengan thresholdWidthtepat, Anda akan mendapatkan tepi yang tampak antialiased.
Tetapi bagaimana Anda memilih thresholdWidth? Jika terlalu kecil, Anda akan mendapatkan aliasing lagi, dan jika terlalu besar ujungnya akan terlalu buram. Selain itu, umumnya akan tergantung pada posisi kamera: jika distdiukur dalam ruang dunia atau unit ruang tekstur, maka thresholdWidthyang bekerja untuk satu posisi kamera akan salah untuk yang lain.
Di sinilah turunan layar-ruang masuk (ya, mereka adalah ddxdan ddyberfungsi seperti yang Anda duga). Dengan menghitung panjang gradien distAnda bisa mendapatkan ide seberapa cepat itu berubah dalam ruang layar dan menggunakannya untuk memperkirakan thresholdWidth, seperti:
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
Anda masih memiliki nilai yang dapat Anda sesuaikan untuk mendapatkan tingkat kelembutan yang diinginkan, tetapi sekarang Anda harus mendapatkan hasil yang konsisten terlepas dari posisi kamera.
derivXdanderivYsebenarnya mewakili.