现代计算机图形学 作业7 解析(4)
其实这一篇文章不算是解析,而是说一下我在实现过程中发现的一个很有意思的点
首先大家看一下我之前生成的这样图片,有没有发现什么奇怪的地方
注意看那个圆球,对比兔子来看,兔子的身上是都有高光的,就是直接光照造成的。但是对于球来说,它的上面有一块黑乎乎的东西。按照我们的经验判断,这个球上面应该也会有一块类似的高光产生,但是这里却没有。这是为什么呢?
最开始我想的是可能因为镜面反射需要一定的角度才能看到高光,所以这里是因为球的位置的原因,还看不到。
我调整了球的位置以后,再次生成图片发现结果基本上是没有变化的。并且我们可以想象这样一条光线,球上面总会有一个位置来反射光源的光的。所以上面那个想法是不对的。
那么大家再看这张图
这两个球是有高光的,所以基本上可以确定是和材质有关的地方出了问题了。因为这个球我用的是银的材质,粗糙度是0.1,而之前那个球是金的材质,粗糙度只有0.001
于是我尝试更改金的材质的粗糙度,发现果然出现了高光。那么问题就是因为粗糙度太小导致的。
那么这时候我们再考虑,粗糙度太小会导致什么情况发生呢?那肯定是会影响到BRDF中半程向量的分布。但是几乎可以确定的是,我们这里的BRDF写的是没有问题的,因为代码基本上都是之前那篇文章中给出的。如果排除了BRDF的实现的问题,问题还有可能在哪里呢?
经过了若干个小时的纠结和反复实现,我发现了一个问题。我尝试关掉了漫反射项的一个判断,就是用来判断这个光线反射的点会不会打到一个光源上。因为如果打到了光源上,这个点的贡献就应该已经被上面的直接光照项算到了,所以这里就会跳过,防止重复累加。
惊奇的是关掉这个项之后,我们的球上面的高光出现了。也就是说,是这里的间接光照项帮我们生成了高光。那不对呀?我上面的直接光照都算了,为什么还是在间接项里才能生成高光。
所以现在的问题就可以锁定到是我们的直接光照项出了问题。我尝试输出了直接光照项的各个系数,同时对比圆球上面的直接光照和其他平面的直接光照,发现只有一个点很奇怪,就是eval函数返回的值都很小,甚至都是0。
为什么?这时候我们可以把当前已有的线索整理到一起,eval在球面上很小,但是间接光照得到的却是正常的结果。所以这里也启发了我们,直接光照和间接光照的区别,尤其是在eval上的区别,其实入射光是固定的,反射光一个是我们采样光源得到的,一个是用重要性采样得到的。
那么我们可以这样考虑,对于光源上的一个点,他如果通过圆球反射到我们的屏幕中,其实在圆球上对应的也就是那一个点。通过重要性采样得到的光线其实就是我们发出的光线对应的反射的光线,这个光线就是生成的合理的反射光线。但是当我们通过采样来计算直接光照的时候,采样的那个光线并不一定和我们发出的光线形成一个反射的关系。
那么当粗糙程度低的时候,半程向量分布的较为紧凑。所以当我们尝试用一个方向不正确的光线来计算eval的时候,得到的系数就是一个很小的值。
而生成的光线,是我们利用反射计算出来的,得到的光线本身就会符合半程向量的分布,所以自然eval也是正确的
说白了就是我们用光源采样的光线是不合适的,人家不用。对于这种低粗糙的材质要他自己生成才行
那么解决问题的方法也就很明确了,我们可以判断直接光照项产生的贡献,当直接光照项产生的贡献很小的时候,说明可能是光线采样出了问题,这时候我们就让间接光帮我们找光源就行。
最后给出结果
文章评论