我一直在使用PBRT,在Rust中实现我自己的版本。现在我正在研究阴影射线,看起来pbrt对镜面的行为没有任何解释,它把像完美玻璃一样的材料当作阴影不透明的东西。我决定尝试实现一个解释这种行为的版本,但是我没有看到任何视觉上的区别。忽略导致我的一些线程被卡住的错误,最上面的是我试图对镜面行为进行解释的尝试,而最下面的是一个“正常”的实现,它投射出一条射线来查看它是否击中了光线。


我看不出地面看上去有什么不同,我也不相信它应该看起来像一个完美的镜面玻璃模型。我的实现如下(它是用Rust表示的,所以我进行了注释,以了解一般的想法):
pub fn occlusion_intersects(&self, ray: &Ray, tmin: f64, tmax: f64, depth: i32) -> Option<HitRecord> {
// find intersection with scene
let ans = self.intersects(ray, tmin, tmax);
// if no intersection was found, return None
if ans.is_none() {
return None
}
let mut ans = ans.unwrap(); // rust stuff, ignore this
// compute the bsdf for the material
Material::compute_scattering_default(&mut ans);
// we only want to specular transmission or reflection
let bsdf_type = BSDF_TRANSMISSION | BSDF_REFLECTION | BSDF_SPECULAR;
// sample_f returns a new outgoing direction according to a bsdf that matches
// one of the types above, or (0, 0, 0) if no matching bsdfs.
let (wi, .. ) = ans.bsdf.sample_f(&ans.wo, bsdf_type);
// if there was no specular bsdf or we've recursed too many times:
if (wi == util::zero_vector() || depth == MAX_DEPTH {
// then return the current intersection to check if it
// hit the expected light object
return Some(ans);
}
// otherwise make a new ray going in the new specular direction
let new_ray = ans.spawn_ray(&wi);
// and return that answer
return self.occlusion_intersects(&new_ray, tmin, tmax, depth + 1);
}作为参考,默认的实现是:
pub fn occlusion_intersects(&self, ray: &Ray, tmin: f64, tmax: f64, depth: i32) -> Option<HitRecord> {
// return the first intersection, ignore all specular behavior
return self.intersects(ray, tmin, tmax);
}我的实现有什么问题吗?我有点猜到它将如何工作,但在评论中所写的逻辑对我来说是有意义的。
发布于 2020-12-14 23:39:59
击中玻璃表面或类似物体的阴影射线会停止,因为没有从光源到阴影点的直接路径--有一块玻璃挡在路上。
对于完美的镜面传输/反射,您可以继续跟踪阴影射线,因为对于给定的传入向量,只有一个可能的输出矢量
这是行不通的,因为透射/反射会改变光线的方向。阴影射线大概是通过指向光源而产生的,但是在透射/反射之后,它很可能不会再击中光源了。
直接向光源发射光线的想法可以看作是一种抽样策略,目的是利用光线最有可能来自哪个方向的知识,并将你的光线放入这些方向。如果你是通过镜面相互作用而不是直接从光源接收光,你就不知道你应该从哪个方向取样。
我想,对于简单的情况,比如玻璃球体,你可以用代数方法解出一条光路,它会折射到光源上的某个点。然后你就可以沿着那条路追踪影子射线了。但是,当你进入像龙一样复杂的几何学中时,就没有现实的方法来计算光线将从哪个方向进入。
当镜面如玻璃或金属聚焦到漫射表面时,会产生腐蚀性。由于这个问题,腐蚀性是香草路径追踪的一个臭名昭著的痛点--没有办法知道在哪里集中你的样本,让你的射线击中光源,所以你能做的最好的就是从各个方向(或BRDF的样品),并希望足够多的射线找到一个光源。从技术上讲,路径跟踪可以正确地呈现焦散,但要做到这一点需要大量的样本。
更实际地说,这个问题可以通过使用光子映射(正是为了处理焦散问题而发明的)来解决,或者是一些像大都会和朋友这样的路径引导方法,它们可以“发现”焦散点,并动态地将样本集中在它们周围。
https://computergraphics.stackexchange.com/questions/10493
复制相似问题