我正在看Smallpt (http://www.kevinbeason.com/smallpt),更具体地说是在俄罗斯轮盘赌部分。实际上,RR用于代码的两个位置:第一,确定射线的终止;第二,用于电介质的渲染。
这是射线终止情况的代码(扩展代码版本):
// p = maximum reflectance
// fr = BRDF
double p = fr.x > fr.y && fr.x > fr.z ? fr.x : fr.y > fr.z ? fr.y : fr.z;
if ( ++depth > 5 )
if ( erand48(Xi) < p )
fr = fr * ( 1 / p );
else
return obj.emission;
在五次反弹之后,RR被用来确定射线路径是否继续。如果继续,BRDF将被缩放以补偿它。这对我来说没问题。
在第二个代码段中还使用RR来选择介质渲染过程中的折射或传输(扩展代码版本):
double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;
double Tr = 1 - Re;
double P = .25 + .5 * Re;
double RP = Re / P;
double TP = Tr / ( 1 - P );
Vec Lo; // output radiance
if ( depth > 2 )
if ( erand48(Xi) < P )
Lo = radiance(reflRay,depth,Xi) * RP;
else
Lo = radiance(Ray(x,tdir),depth,Xi) * TP;
else
Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;
根据上面的代码,如果光线反弹了两次,路径就会递归地分支。然而,在两次反弹之后,RR被用来选择要遵循的路径。这对我也没问题。
有一点令人困惑的是,由两种可能的非分支路径(折射和透射)返回的亮度是缩放的。据我所知,在反射和传播方面有不同的可能性。但是,如果Re = 0.3,Tr = 0.7,100射线击中地表,大约30%的射线会被反射,70%的射线会被发射。在这种情况下,我知道没有路径终止,也没有能量损失,所以不会有任何补偿。
因此,我的前两个问题是:为什么这些辐射被放大?它们应该被缩放,还是根本不缩放就能工作呢?
我的第三个问题与定标因素有关:为什么作者使用P,RP和TP而不是Re和Tr?
任何关于这个主题的好阅读的暗示也是非常欢迎的!!
谢谢!
发布于 2017-07-27 14:09:19
所反映和传递的价值需要按比例加以调整,因为它们的抽样与其贡献不成比例。您将注意到是根据P而不是Re来决定是反射还是传输。
关于为什么在一开始就进行了缩放,只有作者才能给出明确的答案。我的猜测是,这样做是为了防止极小概率产生的极端值。假设Re为0.001,并且使用时不进行缩放。只有1/ 1000的射线会反射,而该射线的贡献将乘以1000。在每像素64射线的渲染中,这将留下非常可见的人工制品,因为不是每个像素都会得到反射光线。另一方面,这段代码的缩放可以确保光线预算在反射和透射之间的分布更加均匀,并且保证每条潜在路径至少有25%或射线。
关于路径跟踪的进一步阅读,没有比www.pbrt.org更好、更全面的资源了--书和源代码都值得一读。
https://computergraphics.stackexchange.com/questions/5414
复制相似问题