Dalam istilah yang sepenuhnya teknis, fwidth(p)
didefinisikan sebagai
fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))
Dan dFdx(p)
/ dFdy(p)
adalah turunan parsial dari nilai p
sehubungan dengan x
dan y
layar dimensi. Jadi mereka menunjukkan bagaimana nilai p
berperilaku ketika pergi satu piksel ke kanan ( x
) atau satu piksel naik ( y
).
Sekarang bagaimana mereka bisa dihitung secara praktis? Nah, jika Anda tahu nilai piksel tetangga untuk p
, Anda bisa menghitung derivasi tersebut sebagai perbedaan hingga langsung sebagai perkiraan untuk turunan matematika aktual (yang mungkin tidak memiliki solusi analitik yang tepat sama sekali):
dFdx(p) := p(x+1) - p(x)
Tapi tentu saja sekarang Anda mungkin bertanya, bagaimana kita bahkan tahu nilai-nilai p
(yang nantinya bisa menjadi nilai yang dihitung secara sewenang-wenang di dalam program shader) untuk piksel tetangga? Bagaimana kita menghitung nilai-nilai itu tanpa menimbulkan overhead besar dengan melakukan seluruh perhitungan shader dua (atau tiga) kali?
Nah, Anda tahu, nilai-nilai tetangga dihitung pula, karena untuk piksel tetangga Anda juga menjalankan shader fragmen. Jadi yang Anda butuhkan hanyalah akses ke permintaan shader fragmen tetangga saat dijalankan untuk piksel tetangga. Tetapi itu bahkan lebih mudah, karena nilai-nilai tetangga juga dihitung pada waktu yang bersamaan.
Rasterizer modern menyebut fragmen shader dalam ubin yang lebih besar dengan lebih dari satu piksel tetangga. Paling tidak itu adalah grid 2x2 piksel. Dan untuk setiap blok piksel seperti itu, shader fragmen dipanggil untuk setiap piksel dan doa-doa itu berjalan dalam langkah kunci paralel sempurna sehingga semua perhitungan dilakukan dalam urutan yang persis sama dan pada waktu yang sama persis untuk masing-masing piksel dalam blok tersebut. (yang juga mengapa bercabang di shader fragmen, sementara tidak mematikan, harus dihindari jika memungkinkan, karena setiap doa blok harus menjelajahi setiap cabang yang diambil oleh setidaknya satu dari doa, bahkan jika itu hanya membuang) hasilnya setelah itu, seperti juga dikemukakan dalam jawaban untuk pertanyaan terkait ini). Jadi setiap saat, sebuah shader fragmen secara teoritis memiliki akses ke nilai-nilai shader fragmen piksel yang berdekatan. Dan sementara Anda tidak memiliki akses langsung ke nilai-nilai, Anda memiliki akses ke nilai-nilai dihitung dari mereka, seperti fungsi turunan dFdx
, dFdy
, fwidth
, ...
dFdx(p) = p(x1) - p(x)
, makax1
dapat berupa salah satu(x+1)
atau(x-1)
, tergantung pada posisi pikselx
di quad. Either way,x1
harus berada di warp / wavefront yang sama denganx
. Apakah saya benar?