博主刚放假回家就进了医院,今天刚完事儿,来续写第二本书
Ready
我们来总结一下上一本书的笔记中我们的一些规定
1. 数学表达式
我们采用小写粗黑体代表向量,大写粗黑体代表矩阵,其他代表标量
2.我们将eye(or camera)发出的光线称为视线(sight)
3.我们目前将所有的非特定(不专属于任何一个类)的通用物理数学运算函数封装到泛型库中,并以lvgm命名空间限定,暂时不准备划分子命名空间
4.我们写库,拟采用全hpp书写,因.h和.cpp之间关于父类纯虚函数的子类相关声明与实现出现了无法链接的神奇编译错误,问过很多大佬,最后还是采用hpp
基础工程代码见第一本书总结篇
Chapter 1 Motion Blur
今天先来一个开胃菜,一个简单易懂的技术——运动模糊
先看效果
好像我们之前也提到过类似的模糊,例如:散焦模糊(defucos blur)
它和今天的模糊还是有一定区别的,从物理成因上讲,defucos是因为未正确对焦,如果没有玩过生活中的相机也没关系,大家都用手机拍过照吧,有些时候,手机相机打开对着拍摄对象,屏幕中的物体或字迹的边缘是模糊的,通常我们会做一个动作,即,点一下屏幕(会出现一个小框),然后图像就会变清晰(边缘明显)
运动模糊的意思是,现实世界中,相机快门开启的时间间隔内,相机内物体发生了位移,画面最后呈现出来的像素,是移动过程中像素的平均值。它不是由相机造成的,而是由物体运动状态造成的形状模糊,比如,你拍摄一张正在下落小球的照片,它所造成的模糊是在段时间内停留在历史轨迹中的重影
弄清楚这个,就开始我们的正题
如何模拟真实生活中的运动模糊,我们先来回顾一下光线追踪的过程
1. 我们选定屏幕中的一个位置,作为待计算的像素点
2. 从eye发出一条视线指向该上述位置周围的采样点
3. 如果中途有物体相交,那么根据物体表面材质进行视线计算
3. 至多递归计算50次,确定该位置的一个采样值
4. 该位置周围采样100次,计算均值作为该位置的最终像素值
那么我们看一下上述过程中,需要改动哪些地方以支持模拟物体的运动模糊行为
首先,我们只需要模拟相机快门开启的时间间隔内的物体运动情况,所以,物体一定有一个运动的起点和终点位置
如果是球体,我们用球心代表运动的位置(heart1,heart2),另外相机时间间隔是一段时间,需要起止时间点确定(time1,time2)
其次,我们模拟物体运动模糊,还要根据相机原理:画面最后呈现出来的像素,是移动过程中像素的平均值
所以,我们依旧采用随机取样,我们之前已经确定采样像素点为100个,采样周围点是为了抗锯齿,这一节我们更重要的是要采样物体的运动位置
我们有物体运动的起止位置和起止时间点(确定运动时间间隔),所以我们取0~1的随机数作为物体从heart1到heart2运动路径长度比例,进而确定物体在该随机时刻的具体位置heart,我们取多个随机时间进行采样,之后再进行均值处理,作为移动过程中像素的平均值
完成上述理论,还需在光线追踪过程中下手
第一步就不用说了,就是确定屏幕位置
第二步就很重要了,视线发出就要接触物体,也就是说视线产生就要确定该时刻的物体具体位置,因为它要和物体进行相交计算,所以,视线承担着记录当前时间点的作用
而我们还需要做运动位置采样,所以,eye需要发出多条视线,基于不同的随机时间,这样我们就做到了根据不同的随机时间发出多条采样视线对物体的运动位置进行采样
我们不妨把抗锯齿的采样和运动位置采样视线生成放在一起
ray.hpp