Kết quả Mật độ xác suất trong Trình theo dõi đường dẫn cho các đường dẫn sử dụng Ước tính sự kiện tiếp theo


7

Tôi đang cố gắng thực hiện Trình theo dõi đường dẫn tên miền Gradient của riêng mình bằng cách tuân theo mã của anh chàng đã thực hiện nó:

https://gist.github.com/BachiLi/4f5c6e5a4fef5773dab1

Tôi đã xoay sở để trải qua các bước khác nhau nhưng tôi muốn làm nhiều thứ hơn nữa. Tôi đã mở rộng mã trong tài liệu tham khảo bằng cách thực hiện ước tính sự kiện tiếp theo và đây là một số kết quả.

Hình ảnh Path Tracer bình thường:

Đường dẫn cơ bản

Hình ảnh kết quả của Gradient Domain:

Hình ảnh tên miền Gradient không có ước tính sự kiện tiếp theo

Kết quả đã tốt .. nhưng như đã nói trước đây, tôi muốn một cái gì đó nhiều hơn nữa. Vì vậy, tôi đã triển khai Dự toán sự kiện tiếp theo và đây là kết quả của Trình theo dõi đường dẫn cơ bản:

Đường dẫn Tracer với NEE

Đây là mã của tôi:

private Vector3 SampleWithNEE( Ray ray )
{
  // prepare
  Vector3 T = (1,1,1), E = (0,0,0), NL = (0,-1,0);
  int depth = 0;
  // random walk
  while (depth++ < MAXDEPTH)
  {
    // find nearest ray/scene intersection
    Scene.Intersect( ray );
    if (ray.objIdx == -1) break; //if there is no intersection
    Vector3 I = ray.O + ray.t * ray.D; //go to the Hit Point on the scene
    Material material = scene.GetMaterial( ray.objIdx, I );
    if (material.emissive) //case of a light
    {
        E += material.diffuse;
        break;
    }
    // next event estimation
    Vector3 BRDF = material.diffuse * 1 / PI;
    float f = RTTools.RandomFloat();
    Vector3 L = Scene.RandomPointOnLight() - I;
    float dist = L.Length();
    L = Vector3.Normalize( L );
    float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );
    float NdotL = Vector3.Dot( ray.N, L );
    if (NdotL > 0)
    {
        Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point
        Scene.Intersect( r );
        if (r.objIdx == -1) //no occlusion towards the light
        {
            float solidAngle= (nldotl * light.getArea()) / (dist * dist);
            E += T * (NdotL) * solidAngle * BRDF * light.emission;
        }
    }
    // sample random direction on hemisphere
    Vector3 R = DiffuseReflectionCosWeighted( ray.N );
    float hemi_PDF = Vector3.Dot( R, ray.N ) / PI;
    T *= (Vector3.Dot( R, ray.N ) / hemiPDF) * BRDF;
    ray = new Ray( I + R * EPSILON, R, 1e34f );
  }
  return E;
}

Mọi thứ hoạt động thực sự tốt và kết quả được hiển thị với hình trên. Một điều nữa: tôi chỉ có các bề mặt khuếch tán trong cảnh của mình.

Bây giờ, vấn đề là trong phương pháp này tôi sử dụng 2 loại PDF:

  • người ta đưa ra bằng cách lấy mẫu ngẫu nhiên ánh sáng trong Dự đoán ánh sáng trực tiếp của Dự toán sự kiện tiếp theo, thực sự rằng SolidAngle là PDF của chúng tôi, hoặc tốt hơn là 1 / PDF.
  • trong khi bản PDF thứ hai là bản PDF được dẫn đầu bằng việc sử dụng DiffuseReflectionCos WEighted mang lại một bản PDF tương đương với CosTheta / PI .

Mọi thứ đều ổn cho đến nay và đối với bất kỳ chi tiết triển khai nào, bạn chỉ cần nhìn vào mã của tôi nhưng các vấn đề đi kèm với Trình theo dõi đường dẫn Gradient của tôi. Thật vậy, ở đó, cũng như trong liên kết tham chiếu ở trên do Tzu-Mao Li thực hiện, tôi cần mật độ xác suất cuối cùng của toàn bộ một đường dẫn để tính toán hình ảnh gradient cuối cùng. Làm thế nào tôi tính toán nó trong trường hợp không có Dự toán sự kiện tiếp theo (NEE)? Trong trường hợp đó (vì tôi chỉ có các bề mặt Diffuse), xác suất này là sản phẩm của CosTheta / PI tại mỗi lần nảy trong cảnh. Mọi thứ đều ổn và hình ảnh gradient kết quả được hiển thị ở trên.

Thay vào đó, trong trường hợp tôi sử dụng NEE, mọi thứ sẽ không hoạt động nữa vì Mật độ Xác suất của toàn bộ đường dẫn của tôi thay đổi và tôi không quản lý để hiểu nó như thế nào. Hình ảnh tên miền Gradient kết quả với ước tính sự kiện tiếp theo là:

nhập mô tả hình ảnh ở đây

Tôi cần hiểu cách tính xác suất mật độ cuối cùng của một đường dẫn. Bạn có thể giúp tôi làm điều đó? Cảm ơn trước!

Câu trả lời:


4

Tôi không có bất kỳ kinh nghiệm nào với Truy tìm đường dẫn tên miền Gradient, nhưng đây là suy nghĩ của tôi:

Dường như có một vấn đề khác

Nếu bạn nhìn kỹ vào các gai nhọn của hình ảnh cuối cùng, bạn sẽ thấy rằng tất cả chúng đều được chiếu sáng từ cùng một hướng - ở phía trên bên trái của chúng ở góc 45 độ nhất quán. Hình cầu cũng dường như được thắp sáng từ góc này, chứ không phải từ phía trên bởi nguồn sáng.

Điều này khó có thể được giải thích bằng một ước tính xác suất không chính xác cho một đường dẫn. Tôi hy vọng sẽ có một vấn đề khác với mã, rằng những biến dạng này đang ám chỉ.

Do đó tôi sẽ giải quyết hai điểm riêng biệt này:

  1. Bạn muốn biết cách tính Mật độ Xác suất của một đường dẫn khi sử dụng Ước tính Sự kiện Tiếp theo.
  2. Có bằng chứng về một số vấn đề không liên quan đến điều này.

Tôi cũng sẽ xem lại mã cho các điểm không quan trọng - nhưng tôi sẽ để lại mã này cho đến khi cần thiết.

Mật độ xác suất của một đường dẫn khi sử dụng Ước tính sự kiện tiếp theo

Nhìn vào bài báo mà mã bạn đang theo dõi có vẻ như ánh xạ dịch chuyển mới được mô tả trong phần 5.2 được xác định theo các đặc tính phản chiếu của các bề mặt được tìm thấy ở các đỉnh của đường dẫn. Tôi phải nhấn mạnh rằng tôi không có hiểu biết đầy đủ về điều này, nhưng nó gợi ý rằng Ước tính sự kiện tiếp theo có thể không yêu cầu thay đổi trong phương pháp này, vì các bề mặt gặp phải sẽ giống nhau. Hy vọng rằng một khi các vấn đề khác được làm sáng tỏ, sẽ dễ dàng hơn để đánh giá xem hình ảnh có chính xác hay không.

Lưu ý rằng phần 5.2 của bài báo đã đề cập (ngay bên dưới Hình 10) mà họ tính đến việc lấy mẫu bộ phát " sử dụng BSDF hoặc lấy mẫu khu vực ".

Sự khác biệt với Ước tính sự kiện tiếp theo là việc lấy mẫu khu vực xảy ra ở mọi đỉnh của đường dẫn, nhưng đối với tôi điều này không rõ ràng rằng điều này sẽ gây ra vấn đề.

Thực tế là cảnh của bạn chỉ sử dụng các bề mặt khuếch tán có nghĩa là đường dẫn bù trong hầu hết các trường hợp sẽ nối lại đường cơ sở ở đỉnh thứ hai, do đó bạn chỉ cần tính toán lại lấy mẫu khu vực cho đỉnh đầu tiên của đường bù.

Nguyên nhân của hướng chiếu sáng không chính xác

Khi đọc qua mã để làm quen với cách nó hoạt động, tôi nhận thấy rằng đã NLdotLđược tính toán, nhưng sau đó không được sử dụng. Một tìm kiếm văn bản cho thấy rằng sự xuất hiện duy nhất khác có một trường hợp khác : nldotl. Dưới đây là hai biến trong ngữ cảnh (dòng đầu tiên và thứ chín của đoạn trích này):

float NLdotL = Math.Abs( Vector3.Dot( NL, -L ) );
float NdotL = Vector3.Dot( ray.N, L );
if (NdotL > 0)
{
    Ray r = new Ray( I + L * EPSILON, L, dist - 2 * EPSILON ); //make it a tiny bit shorter otherwise I risk to hit my starting and destination point
    Scene.Intersect( r );
    if (r.objIdx == -1) //no occlusion towards the light
    {
        float solidAngle= (nldotl * light.getArea()) / (dist * dist);
        E += T * (NdotL) * solidAngle * BRDF * light.emission;
    }
}

nldotlkhông được xác định, kết quả của mã là hành vi không xác định. Trong thực tế, chương trình có khả năng hoạt động như thể nldotlbằng 0 hoặc đối với một số trình biên dịch có lẽ là một giá trị tùy ý không đổi hoặc thậm chí là một giá trị tùy ý khác nhau ở mỗi lần lặp. Đối với trình biên dịch cụ thể của bạn, nó dường như là một giá trị không đổi và tôi hoàn toàn nghi ngờ đây là nguyên nhân của sự liên kết đặc biệt của góc chiếu sáng trên tất cả các đốm và hình cầu. Nếu có một vấn đề đóng góp khác, việc phân tích nó trong một câu hỏi riêng sẽ dễ dàng hơn một khi vấn đề ban đầu này đã được khắc phục.

Có thể đáng cân nhắc khi sử dụng trình biên dịch và / hoặc cài đặt cờ gây ra lỗi hoặc ít nhất là cảnh báo cho các biến không xác định, vì loại lỗi này rất dễ mắc phải và rất dễ bỏ qua sau này.

Đóng góp thêm của nguồn sáng

Dường như có một vấn đề khác sẽ khiến kết quả không chính xác theo cách tinh tế hơn, không có sự biến dạng rõ ràng. Do Ước tính Sự kiện Tiếp theo, nguồn sáng đang đóng góp cho mỗi bước dọc theo đường dẫn. Điều này có nghĩa là nó không nên đóng góp nếu đường dẫn chạm trực tiếp vào nguồn sáng. Mặt khác, đối với đường dẫn đó, nguồn sáng sẽ đóng góp hai lần. Bạn có thể sửa lỗi này bằng cách thay đổi:

if (material.emissive) //case of a light
{
    E += material.diffuse;
    break;
}

đến:

if (material.emissive) //case of a light
{
    break;
}

Điều này sẽ đóng góp bằng không từ giao điểm với ánh sáng.

Lưu ý rằng vì tôi chỉ có thể thấy một chức năng này, tôi không thể đoán liệu điều này cũng sẽ làm cho ánh sáng xuất hiện màu đen trong hình ảnh. Bạn có thể hoặc không cần điều chỉnh các tia bắt đầu từ máy ảnh và chiếu trực tiếp vào ánh sáng.


Đánh giá mã

Tia hữu hạn

Tôi đã quen xác định một tia là một nửa dòng vô hạn - có điểm bắt đầu nhưng không có điểm kết thúc. Tôi nhận thấy rằng mã này cung cấp cho một tia cả điểm bắt đầu và chiều dài. Nơi duy nhất tôi có thể thấy một lý do cho điều này là khi kiểm tra tia sáng đối với nguồn sáng: mã kiểm tra rằng không có giao điểm nào trên đường tới ánh sáng, do đó, các giao điểm phía sau ánh sáng (hoặc trên chính ánh sáng) phải loại trừ Ở tất cả các vị trí khác, tia được xác định với độ dài giả vô hạn ( 1e34f).

Gợi ý sau đây sẽ không ảnh hưởng đến tính chính xác của mã của bạn, nhưng nó có thể dễ đọc hơn và tránh bạn phải giải quyết nhu cầu vô cực và phải tính đến epsilon hai lần.

Nếu tia chỉ đơn giản là điểm bắt đầu và hướng, thì các tia bóng có thể đơn giản kiểm tra xem giao điểm đầu tiên là ánh sáng, thay vì kiểm tra xem không có giao điểm. Ví dụ: bằng cách thay thế:

if (r.objIdx == -1) //no occlusion towards the light

với:

if (r.objIdx == LIGHT) // There is no object intersected before the light

Ở đây tôi sử dụng LIGHTnhư một trình giữ chỗ cho id của nguồn sáng, vì phần đó của mã không được bao gồm trong câu hỏi.

  • Điều này sẽ luôn luôn sai nếu ánh sáng bị che khuất bởi một vật ở gần.
  • Điều này sẽ luôn luôn đúng nếu tia sáng chiếu vào trước các vật thể ở xa hơn.

Do đó, điều này tương đương với mã hiện tại, nhưng không yêu cầu tia lưu trữ độ dài.

Đèn không phản chiếu

Mã hiện mô hình ánh sáng và bề mặt riêng biệt. Điều này có nghĩa là nếu một vật thể là ánh sáng thì nó chỉ phát ra và không phản chiếu ánh sáng từ các vật thể khác.

Điều này gây ra sự khác biệt không đáng kể trong cảnh ví dụ trong câu hỏi, có một ánh sáng duy nhất. Tuy nhiên, nếu được sử dụng với một số đèn mờ hơn, điều đáng chú ý hơn là chúng không sáng nhau. Trong nhiều trường hợp, sự khác biệt sẽ không được chú ý, vì vậy đây không phải là vấn đề nếu nó hoạt động cho các cảnh bạn muốn kết xuất.

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.