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:
Hình ảnh kết quả của Gradient Domain:
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:
Đâ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à:
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!