Trong thuật ngữ hoàn toàn kỹ thuật, fwidth(p)
được định nghĩa là
fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))
Và dFdx(p)
/ dFdy(p)
là các dẫn xuất một phần của giá trị p
đối với kích thước x
và y
màn hình. Vì vậy, chúng biểu thị giá trị của p
hành vi khi đi một pixel sang phải ( x
) hoặc một pixel lên ( y
).
Bây giờ làm thế nào họ có thể được tính toán thực tế? Chà, nếu bạn biết các giá trị của các pixel lân cận p
, bạn chỉ có thể tính các đạo hàm đó là các khác biệt hữu hạn trực tiếp như là một xấp xỉ cho các đạo hàm toán học thực tế của chúng (có thể không có giải pháp phân tích chính xác nào cả):
dFdx(p) := p(x+1) - p(x)
Nhưng tất nhiên bây giờ bạn có thể hỏi, làm thế nào chúng ta thậm chí biết các giá trị của p
(mà sau đó có thể là bất kỳ giá trị được tính toán tùy ý nào trong chương trình đổ bóng) cho các pixel lân cận? Làm thế nào để chúng ta tính toán các giá trị đó mà không phải chịu chi phí lớn bằng cách thực hiện toàn bộ tính toán shader hai (hoặc ba) lần?
Chà, bạn biết không, những giá trị lân cận đó được tính toán bằng mọi giá, vì đối với pixel lân cận, bạn cũng chạy một shader mảnh. Vì vậy, tất cả những gì bạn cần là truy cập vào lời gọi shader mảnh vỡ lân cận này khi chạy cho pixel lân cận. Nhưng nó thậm chí còn dễ dàng hơn, bởi vì những giá trị lân cận đó cũng được tính toán cùng một lúc.
Các trình raster hiện đại gọi các shader mảnh trong các ô lớn hơn nhiều pixel lân cận. Ở mức nhỏ nhất sẽ là một lưới pixel 2x2. Và với mỗi khối pixel như vậy, shader mảnh được gọi cho từng pixel và các lệnh đó chạy theo bước khóa song song hoàn hảo để tất cả các phép tính được thực hiện theo cùng một thứ tự chính xác và cùng một lúc cho từng pixel đó trong khối (đó cũng là lý do tại sao phân nhánh trong shader mảnh, trong khi không gây chết người, nên tránh nếu có thể, vì mỗi lần gọi của một khối sẽ phải khám phá mọi nhánh được lấy bởi ít nhất một trong số các lệnh, ngay cả khi nó bị ném đi kết quả sau đó, cũng như đã nhấn mạnh trong các câu trả lời cho câu hỏi liên quan này). Vì vậy, tại bất kỳ thời điểm nào, về mặt lý thuyết, một shader mảnh vỡ có quyền truy cập vào các giá trị shader mảnh của các pixel lân cận. Và trong khi bạn không có quyền truy cập trực tiếp đến những giá trị đó, bạn có quyền truy cập vào các giá trị tính toán từ họ, như các chức năng phái sinh dFdx
, dFdy
, fwidth
, ...
dFdx(p) = p(x1) - p(x)
, sau đóx1
có thể là(x+1)
hoặc(x-1)
, tùy thuộc vào vị trí của pixelx
trong quad. Dù bằng cách nào,x1
phải ở trong cùng một sợi dọc / sóngx
. Tôi có đúng không?