Tiện ích của bán kính bình phương và bán kính bình phương nghịch đảo cho các tính toán ánh sáng là gì?


16

Trên một trong các slide từ "DirectX 11 Rendering trong Battlefield 3" PowerPoint tôi nhận thấy mã folowing:

struct Light {
    float3 pos; float sqrRadius;
    float3 color; float invSqrRadius;
}

Tôi không hiểu tại sao họ sẽ lưu trữ bán kính bình phương và thậm chí cả bình phương nghịch đảo (mà tôi tin chỉ đơn giản là bán kính 1 bình phương) thay vì chỉ đơn giản là lưu trữ bán kính? Làm thế nào họ sử dụng dữ liệu này trong tính toán của họ? Hơn nữa, những gì về đèn hình nón và đèn đường? Cấu trúc này phải chỉ dành cho đèn điểm, tôi không thể thấy nó hoạt động cho các loại khác - không có đủ dữ liệu. Tuy nhiên, tôi rất muốn biết làm thế nào họ sử dụng hình vuông và invSapes.

CẬP NHẬT: Ok cuối cùng tôi đã nhận được nó.

Dưới đây là phương trình suy giảm ánh sáng cổ điển, dễ dàng tìm thấy trên mạng:

float3 lightVector = lightPosition - surfacePosition;

float attenuation = saturate(1 - length(lightVector)/lightRadius);

Nó tương đối tốn kém như length(lightVector)thực sự làm điều này:

length(lightVector) = sqrt(dot(lightVector, lightVector);

hơn nữa hoạt động phân chia (/lightRadius)cũng khá tốn kém.

Thay vì tính toán suy giảm ánh sáng theo cách này, bạn có thể tính toán theo cách sau, sẽ nhanh hơn nhiều:

attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);

trong đó invRadiusSqr có thể được tính toán trước ở mức CPU và được truyền dưới dạng hằng số shader.

Hơn nữa, kết quả là bạn bị suy giảm ánh sáng bậc hai (thay vì tuyến tính trong trường hợp trước), điều này thậm chí còn tốt hơn, vì ánh sáng IRL đã cho thấy có sự sụp đổ bậc hai.

Cảm ơn mọi người đã giúp đỡ!


13
Đệm lót. Các shader được căn chỉnh 16byte. Và nếu bạn xem cách mã được hình thành, bạn sẽ thấy rằng nó sẽ được đóng gói thành hai float4. Tại sao không lưu trữ một cái gì đó hữu ích khi bạn sẽ nhận được nó miễn phí từ bộ đệm?
Tordin

Câu trả lời:


23

Đây chỉ đơn giản là một loại tối ưu hóa được đưa ra invSqrRadius = 1/SqrRadius, thay vì tính bán kính bình phương nghịch đảo cho mỗi ánh sáng mỗi khi chúng chỉ lưu vào bộ đệm, lý do là sự phân chia thường là hoạt động "chậm" ít nhất khi so sánh với phép nhân.

Tối ưu hóa này có liên quan đặc biệt là:

  • khi hoạt động được thực hiện một lượng lớn thời gian cho mỗi ánh sáng, do đó, việc lưu trữ giá trị sẽ giải phóng thêm chu kỳ CPU / GPU
  • Và giả sử thời gian truy cập bộ nhớ để đọc giá trị thực sự nhanh hơn so với tính toán lại nó.

Về cách nó được sử dụng, tôi không chắc chắn về việc triển khai cụ thể của chúng, nhưng về việc 1/sqrRadiusnày, nó chỉ đơn giản được sử dụng cho sự suy giảm ánh sáng, sự sụp đổ và loại bỏ. Nó cũng phù hợp với hướng và ánh đèn sân khấu, sự khác biệt duy nhất trong trường hợp ánh đèn sân khấu là bạn cần tính toán hệ số ánh sáng sau khi áp dụng suy hao . Về ánh sáng định hướng như mặt trời, nó thường không có bất kỳ sự suy giảm hoặc giảm, vì vậy tôi đoán nó sẽ bị bỏ qua.

[EDIT] Chỉ cần giải thích thêm, đó không phải là dữ liệu không liên quan. Ánh sáng chiếu xạ có thể được tính bằng phương trình sau:

E = Phi / 4 * pi * rSqr;

Ở đâu

E là mật độ diện tích của từ thông.

Phi là thông lượng rạng rỡ.

4 * pi * rSqr là diện tích bề mặt của một hình cầu.

Phương trình này giải thích tại sao lượng năng lượng nhận được rơi ra với khoảng cách bình phương.

Một điểm khác là bạn cần tính khoảng cách giữa đỉnh và ánh sáng để tính toán sự đóng góp ánh sáng trên một đỉnh cụ thể (giá trị này không có khả năng được lưu vào bộ đệm), đỉnh có thể nằm trong hoặc ngoài phạm vi ánh sáng đưa chúng ta đến điểm tiếp theo nơi Radius Squarehữu ích cho việc loại bỏ.

Nếu bạn muốn có một ví dụ thực tế để tính toán giảm ánh sáng và loại bỏ ánh sáng, thì điều này đặc biệt hữu ích trong các trình kết xuất hoãn lại dựa trên lát gạch, đây là một ví dụ .


Nguyền rủa, bạn đánh tôi 7 giây! ;) (và với câu trả lời toàn diện hơn nữa!)
Trevor Powell

Cảm ơn các bình luận chi tiết, đặc biệt cho các liên kết! Từ những gì tôi hiểu được từ liên kết sau, Battlefield 3 lưu trữ không phải bán kính mà là khoảng cách thực tế giữa nguồn sáng và bộ thu ánh sáng, phải không? Đó là giá trị "d" mà họ sử dụng trong bài viết.
cubrman

@cubrman thật khó để suy đoán mà không thấy mã. Tôi đoán rằng đó là bán kính nghịch đảoSqr. Và các phương trình họ sử dụng có thể thay đổi rất nhiều từ bài viết.
Concept3d

Nhưng cho tôi biết, làm thế nào bạn có thể sử dụng một bán kính ánh sáng đảo ngược bình phương trong một tính toán ánh sáng? Mỗi nguồn tôi tìm thấy trên mạng đều nói với tôi rằng tôi cần tìm DISTANCE giữa bề mặt thu và nguồn sáng, chia cái sau cho bán kính ánh sáng ban đầu VÀ THÌ bình phương kết quả. Nơi nào bạn sẽ sử dụng bán kính bình phương hoặc invSqrRadius? Đó dường như là dữ liệu hoàn toàn không liên quan đến tôi.
cubrman

1
@cubrman cập nhật câu trả lời.
Concept3d

6

invSqrRadius không phải là 1 - sqrRadius; đó là 1 / sqrRadius.

Điều đó có nghĩa là bạn có thể nhân với invSqrRadius, thay vì chia cho sqrRadius (vì phép chia thường đắt hơn nhiều so với phép nhân)


6

Các câu trả lời khác ở đây xử lý bán kính hình vuông nghịch đảo, nhưng tôi sẽ xem xét bán kính bình phương thay vào đó (mà khái niệm 3d đã chạm vào, nhưng tôi tin rằng nó đáng để thảo luận thêm).

Những gì hình vuông là hữu ích cho so sánh khoảng cách. Chúng ta biết rằng việc tính toán khoảng cách giữa hai điểm liên quan đến căn bậc hai và căn bậc hai rất tốn kém để tính toán, nhưng nếu tất cả những gì chúng ta muốn làm là so sánh khoảng cách (để tìm ra điểm nào nhỏ hơn hoặc lớn hơn và làm điều gì đó thú vị dựa trên kết quả) chúng ta có thể ném ra căn bậc hai.

Nếu sqrt (x)> sqrt (y) thì đó cũng là trường hợp x> y.

Đối với ánh sáng, bán kính bình phương giống như khoảng cách giữa tâm của ánh sáng và phạm vi tối đa của nó - dĩ nhiên là bình phương.

Đối với tính toán ánh sáng, điều này có thể được sử dụng cho trường hợp sớm. Nếu khoảng cách giữa điểm bạn đang chiếu sáng và tâm của ánh sáng (bình phương) lớn hơn bán kính bình phương, thì điểm đó không nhận được ánh sáng và bạn không cần phải chạy phần còn lại của các tính toán. Do đó, đây chỉ là một tối ưu hóa (khá phổ biến) - chúng ta có thể sử dụng bán kính bình phương để so sánh khoảng cách mà không cần căn bậc hai đắt tiền, và với chi phí chỉ là một sản phẩm trừ và chấm.

Tôi, tất nhiên, không biết liệu đây có chính xác là những gì BF3 đang sử dụng không, nhưng tôi hy vọng rằng tôi sẽ không đi quá xa.


Vì vậy, nếu tôi hiểu bạn chính xác, mã sẽ là: if (dot ((lightPos - SurfacePos), (lightPos - SurfacePos))> lightRadiusSqr) không làm ánh sáng, phải không?
cubrman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.