好久没写这样的系列了,上一次总结渲染的改进,还是4.5的时候。最近,又对KlayGE的渲染做了一些系统性的修改,所以在这里总结一下。
材质系统
原先的材质系统里,diffuse颜色和specular颜色是分开的。要放到GBuffer里的时候,specular颜色就剩下亮度,之后跟光的亮度操作后,从diffuse的颜色恢复出specular颜色。这只是一个情非得已的hack,因为G-Buffer里只有4个通道可供使用,放不下diffuse和specular颜色。
2015年的Physics and Math of Shading里,详细分析了导体、绝缘体、半导体的diffuse和specular分布,得到的结论是,只需要有个albedo的颜色(3通道)以及一个metalness(1通道),就已经足够。因为导体的diffuse是0,绝缘体的specular是一个很小的单色值,而半导体介于两者之间。(详细过程可以看我在知乎上的文章)
绝缘体diffuse和specular都有。specular很弱。
有了这些基础,我们就可以决定对于G-Buffer的改进。原先的diffuse(3通道)和specular亮度(1通道),就可以改成albedo(3通道)和metalness(1通道)。在做shading的时候,用
diffuse = albedo * (1 – metalness)
specular = lerp(0.04, albedo, metalness)
来恢复出diffuse和specular颜色来。这样不但解决了GBuffer空间不足问题,有提供了diffuse和specular的全部信息,而不是只有亮度。
原先的材质系统渲染金属的话,会看着像油腻的塑料。
而现在的方法,同样的数据,看着就像金属了。
全彩色基于物理的光照
有了前面的新材质系统,我们可以更进一步,恢复全彩色并且基于物理的光照。
在KlayGE 4.0里,由于G-Buffer和lighting accumulation buffer的空间限制,我不得不做出一个艰难的决定,放弃在lighting pass用light方向和halfway方向计算fresnel,而改成在shading pass用view方向和normal方向来代替计算fresnel。这样得到的结果不是基于物理的,但能在G-Buffer和lighting accumulation buffer中分别节省出宝贵的2个通道。
有了前面说到的新材质系统,diffuse和specular加起来只要4通道就能保存,这样在技术上就能恢复出全彩色的材质,而不用hack的恢复颜色法。得到的结果specular颜色更正确。另一方面,由于在KlayGE 4.5中已经启用了TBDR的系统,在light indexed和tile based这两条code path中,都已经没有lighting accumulation buffer,而是在shader里循环累积。所以并不受通道数的限制,diffuse和specular都能保持3通道。
有了这些基础,我们就能恢复使用全彩色并基于物理的光照,用全彩色的diffuse和specular,并把fresnel改回在lighting的时候计算。
改之后变成这样:
其实差别不大。主要不同集中在边缘区域,比如右边的拱形区域。
总结
本篇讲了新的材质系统以及如何把它用来改进deferred rendering。下一篇将讲一下另一个改进,tone mapping。
Comments