现在,我们学习最后一个特性,散焦模糊。摄影方面一般称呼其为景深。

我们在真实相机中散焦模糊的原因是因为他们需要一个大洞(而不是针孔)才能收集光线。这会使一切都散焦,但如果我们在镜头孔中贴上镜头,那么在一切焦点处都会有一定的距离。到物体聚焦的那个平面的距离由镜头和胶片/传感器之间的距离控制。这就是为什么当你改变焦点时(这可能发生在你的手机相机中,传感器会移动),你会看到镜头相对于相机移动。真正的相机有一个复杂的复合镜头。 对于我们的代码,我们可以模拟顺序:传感器,然后是镜头,然后是光圈,然后计算出发送光线的位置,然后翻转一次计算的图像(图像在电影上上下颠倒投影)。图形人通常使用薄的近似镜头。

我们也不需要模拟相机内部的任何部分。 为了在相机外部渲染图像,这将是不必要的复杂性。 相反,我通常从镜头表面开始发射光线,并通过在焦点平面(在 focus_dist)上找到胶片的投影,将它们发送到虚拟胶片平面。

为此,我们只需要将射线源放在外观上的磁盘上,而不是从某个角度来看:

 

def random_in_unit_disk():
    p=vec3(0,0,0)
    while True:
        p=2.0*vec3(random(),random(),0)-vec3(1,1,0)
        if p.dot(p) >= 1.0:
            break
    return p
class camera:
    def __init__(self,lookfrom,lookat,vup,vfov,aspect,aperture,focus_dist):
        self.lens_radius=aperture/2
        theta=vfov*pi/180
        half_height=tan(theta/2)
        half_width=aspect*half_height
        self.origin=lookfrom
        self.w=(lookfrom-lookat).unit_vector()
        self.u=vup.cross(self.w).unit_vector()
        self.v=self.w.cross(self.u)
        self.lower_left_corner=self.origin-half_width*focus_dist*self.u-half_height*focus_dist*self.v-focus_dist*self.w
        self.horizontal=2*half_width*focus_dist*self.u
        self.vertical=2*half_height*focus_dist*self.v
    def get_ray(self,s,t):
        rd=self.lens_radius*random_in_unit_disk()
        offset=self.u*rd.x()+self.v*rd.y()
        return ray(self.origin+offset,self.lower_left_corner+s*self.horizontal+t*self.vertical-self.origin-offset)

 

posted on 2018-05-30 21:28  图样司  阅读(330)  评论(0编辑  收藏  举报