Blender EEVEE渲染器存在图像模糊问题以及原因分析
Blender EEVEE渲染器存在图像模糊问题以及原因分析
Blender的EEVEE渲染器在所有版本中都存在一个令人困扰的问题:当采样设置大于1时,输出的图像会出现模糊现象。本文将深入分析这一问题的原因,并探讨可能的解决方案。
直到目前为止(Blender 4.3 alpha),所有版本的Blender EEVEE渲染器均存在渲染出来的图像模糊的问题,表现为当采样(Sampling)设置为大于1的值时,输出的图像就会发生模糊。效果类似于施加了2x2的模糊。为了提高最终输出清晰度,使用EEVEE渲染图像或视频时请将分辨率设置为最终输出的2倍。
下面用同一张图,不同渲染设置用来对比。
第一张图,采样设置为1,此时图像不模糊,但模型会有锯齿。
第二张图,采样设置为64,图像发生模糊
第三张图,Cycles渲染,采样设置为4096
为了减少图像压缩带来的影响,我将第一张和第二张图片裁切一部分并放大4倍。网页版可以右键点击图像新标签页中打开图像来对比。
第二张图片看起来更亮,白色部分扩大,可以看出当采样设置为64时,EEVEE输出的图像确实变模糊了。
原因分析
为什么会这样呢?
模型是由三角形组成的,在渲染时经过一系列过程最终渲染为图像。EEVEE的渲染过程不是光线追踪,而是传统的光栅渲染。这个过程中有一步将三角形变成覆盖屏幕的像素,称为光栅化。这个过程中,对于每个渲染的三角形和每个像素点,这个点要么在三角形里,要么不在三角形里。但是像素实际上是具有体积的,如果三角形没有完全覆盖像素,那么这个点不管是在三角形或者不在三角形中都不合适,实际判定以像素的中心位置来确定是否在三角形中,因此光栅化过程会导致锯齿状的失真。
EEVEE通过多次渲染图像并混合来抗锯齿。每次渲染图像时,添加一个微小的“抖动”让相机在一个像素范围内移动,通过上文所述的过程渲染,对于每个像素,三角形的边缘从原来的覆盖(1)和未覆盖(0)取值变成了许多个0和1取平均值,因此消除了锯齿。
混合多张图像能够消除三角形边缘的锯齿,也能消除各种采样不足产生的噪点,看起来很完美,却有一个意外的效果,所有物体的贴图都变得模糊了。
问题不是出在混合上,而是出在“抖动”上。为了说明这个情况,首先介绍Mipmap。通常游戏引擎和渲染器为了避免物体移动时贴图闪烁,会为贴图生成Mipmap。举例原图尺寸是10241024,Mip 1级为512512,2级时为256256,以此类推,通常会生成到11为止。渲染图像时,根据像素在屏幕中的占比,选择最合适的Mip层级进行采样,当物体离相机很远时,在屏幕上的占比较小,选择mip层级高的贴图进行采样才不会失真。做个比喻:把每个像素看作颜料桶,最终只能输出一个颜色,如果把图像用一个颜料桶表示,那这个颜料桶的颜色只能是整张图像的所有颜色取平均,而不能是图像的某个部分的颜色。
回到模糊问题,不理解Mip也没关系,只需要知道通常渲染时,Mip已经消除了贴图采样缩放的失真问题。那么我们认为正常渲染单张图像时,贴图已经经过抗失真。但是在多张图片混合时,会出现一些问题。如前文所述,EEVEE合成最终输出前会“抖动”相机的位置,拍摄多张图像。对于每个像素来说,其采样位置发生了改变。而贴图在单次渲染时是经过抗失真的,因此会造成模糊。
举个例子,下图代表一个3*2的贴图。
2 2 6
2 2 6
我们只观察其中一个像素,考虑极端情况,它位于图像的中央,抖动使得它的中心位于左上角 2 2 2 2的中心,它的输出值为 (2 + 2 + 2 + 2) / 4 = 2。
接下来一张图像这个像素的中心位于右上角2 2 6 6的中心,它的输出值为(2 + 2 + 6 + 6) / 4 = 4。
最终在eevee的输出为 (2 + 4) / 2 = 3。
有些人认为,这并没有什么问题,这就是图像采样的原理啊。但其实它混合了一些不该混合的像素,它的中心在图像的中心。在不失真的情况下,其值为 (2 + 2) / 2 = 2。(我只是在说明原理,所以没有在采样时乘上系数)
解决方案
这个问题只能由Blender解决,在此之前,你能做的就是提高输出分辨率。
这个问题显然有多种解决方案。第一种是当采样大于1时降低mip层级,使得贴图在采样时失真,最后混合时正常。
第二种方案,采样时修改采样位置,抵消抖动带来的位置移动,使得渲染像素时总是采样像素中心点,避免采样点移动。
想试试?
如果专栏图片压缩不明显的话可以试试。
将渲染器切换到EEVEE,图像贴到物体上直接输出,分辨率设置为512*512,采样设置为64。
已经给Blender提交issue,在Blender解决之前只能通过提高分辨率降低影响,或者切换Cycles渲染器。