Problem
在采样数为200,最大弹射次数为50的情况下,执行光线追踪得到如下结果
以上是问题的对比图,可以看到上述存在以下几个问题
- 反射的光线过于集中,如右侧红色部分
- 存在左上角黑色的死区
- 左侧绿色反射在地板过于明显以至于地板直接变成绿色
问题分析
伪随机失效
因为为加速计算速度,使用了多个线程运行光线计算,推测过于集中的红色部分是否可能是多线程下,随机函数重复输出相同的随机数导致的问题
将线程最大并发数限制为1,发现仍然存在问题,排除伪随机失效的可能
Lambert分析
思考这种相邻的不同材质的颜色渗透是否是正常的,光线追踪的过程实际上是记录光线从光源反弹的过程,每个材质具有不同的材质albedo可以理解为对光线中不同分量的反射能力。
为什么不是反射能力? 我们可以举一种计算情况,如果一个物体,能够吸收所有的光线,也就是说这个物体是个黑体,在外界观察是看不到任何颜色的只是漆黑一片,这个时候如果我们使用albedo表示这个物体的材质时,其对应(0,0,0),因而albedo表征材质中对不同颜色光线的反射能力。
若我们此时有一束光线经过2次弹射,分别从eye->地板->左侧绿墙->顶部光源,那么对应光线的颜色实际上是
$$ color_{eye} = light*M_{green}*M_{white} $$
我们逆向观察从光源(15,15,15)经过绿墙 $M_{green}$ (0.15,0.45,0.15)的反射,此时光线能量绿色在所有颜色分量中占据最高比例,此时为(2.25,6.75,2.25),然后经过白色的地面 $M_{white}$ (0.73,0.73,0.73),因为地面均匀反射各个分量,所以最终颜色倾向于绿色也就不足为奇
注意:这里的只是一个简单的光照模型,并不遵循能量守恒定律
并且,Lambert材质实现没有发现任何逻辑性的错误,因而问题也不是出现在Lambert上面
错误的随机分布范围
经过两轮分析,发现实现的流程上没有任何逻辑上的错误,因而可能是某个功能函数可能存在的计算错误,逐个排查各个随机函数的视线,最终发现在随机生成的单位向量中,使用了默认的随机函数,而没有指定随机函数的范围[-1,1]这导致随机函数实际上仅生成[0,1]范围内的随机单位向量,这也就解释了为什么存在死区和红色区域过于集中的问题。至于绿色部分的过度反射,推测其原理和红色区域类似,反射过于集中导致在其他材质表面呈现明显的绿色