Ray Tracing in One Weekend
Ray Tracing in One Weekend
- 版本:
3.2.3
,2020-12-07
- 光追框架理解
- 工程能力训练
1. ppm 文件格式
1 | # 文件头 |
- 上面例子的图片如下
- windows 可以使用工具 xnview
查看
- xnview 好像不支持
P3
格式,支持P6
格式
- xnview 好像不支持
P3
和P6
格式的唯一区别就是P3
使用 ASCII 码存储,而P6
使用二进制存储- 图像头文件库:stb_image.h
2. 坐标系说明
- 视点:\((0,0,0)\)
- 视窗
- 高度设置为 \(2\),宽度由
aspect ratio
计算得到(一般使用16:9
) - \(z=-1\):
focal length
- 高度设置为 \(2\),宽度由
3. 光线与球求交
\[ \begin{array}{c} (\mathbf{P}(t) - \mathbf{C}) \cdot (\mathbf{P}(t) - \mathbf{C}) = r^2\\ (\mathbf{A} + t \mathbf{b} - \mathbf{C}) \cdot (\mathbf{A} + t \mathbf{b} - \mathbf{C}) = r^2\\ t^2 \mathbf{b} \cdot \mathbf{b} + 2t \mathbf{b} \cdot (\mathbf{A}-\mathbf{C}) + (\mathbf{A}-\mathbf{C}) \cdot (\mathbf{A}-\mathbf{C}) - r^2 = 0\\ \end{array} \]
- 简化,令 \(b=2h\)
\[ \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}== \frac{-h \pm \sqrt{h^2 - ac}}{a} \]
- 判断光线是从圆内部射出还是外部射入
1 | bool front_face; |
4. 抗锯齿
- 对每一个像素产生多条光线
5. 漫反射材质
- diffuse
- 随机出射
- 在球体内部随机采样:在一个正方体中采样,判断长度是否落在球体内部
- 上述采样方法,假设出射光线和法线的夹角为 \(\phi\),那么概率分布密度函数系数为 \(\cos^{3}{\phi}\)
- 算出来是 \(\cos^{3}{\phi}\sin{\phi}\)
- 注意是 3D 的
- 因为入射光线和法线的夹角大多较大,因此整体结果偏黑
- 算出来是 \(\cos^{3}{\phi}\sin{\phi}\)
- 朗伯反射的系数应该是 \(\cos{\phi}\)
- 实现方式,在球的表面上均匀采点,小球面均匀采样 \(\mathbf{S}\),等价于大半球面朗伯采样 \(\mathbf{S}_2\)
- 小球面:\(\mathrm{d}\omega\)
- 大球面:\(\mathrm{d}\omega_2\)
\[ \begin{aligned} \mathrm{d}\omega &=\sin{2\phi}\;\mathrm{d}\theta\mathrm{d}2\phi\\ &=2\sin{2\phi}\;\mathrm{d}\theta\mathrm{d}\phi\\ &=4\cos{\phi}\sin{\phi}\;\mathrm{d}\theta\mathrm{d}\phi\\ &=4\cos{\phi}\;\mathrm{d}\omega_2\\ \end{aligned} \]
- 之前还有一种采样方式,随机采一条单位长度的光线,让后判断它和法线是否在同一个法向半球内
- 法向半球采样
不同采样方式 10spp
- 法向半球采样
- 球体表面采样(朗伯采样)
- 球体内部采样,单位化
- 球体内部采样
6. 纯镜面材质
磨砂材质
- 反射方向周围采样一个偏折角
7. 绝缘体材质
- Dielectrics
- Clear materials such as water, glass, and diamonds are dielectrics.
- 同时有折射、反射
- 实现:每次只取一个方向(折射 / 反射)
- 折射定律
\[ \eta \cdot \sin\theta = \eta' \cdot \sin\theta' \]
- 入射方向指向交点,出射方向从交点指出
- 分量分解,出射光线 \(\mathbf{R'}\)
\[ \mathbf{R'}=\mathbf{R'}_{\bot}+\mathbf{R'}_{\parallel} \]
- 垂直法线分量
\[ \begin{array}{c} \eta'\mathbf{R'}_{\bot}=\eta\mathbf{R}_{\bot}=\eta(\mathbf{R}-\mathbf{R'}_{\parallel})=\eta(\mathbf{R}+\cos\theta\mathbf{n})=\eta(\mathbf{R}-(\mathbf{n}\cdot\mathbf{R})\mathbf{n})\\ \mathbf{R'}_{\bot}=\dfrac{\eta}{\eta'}(\mathbf{R}-(\mathbf{n}\cdot\mathbf{R})\mathbf{n})\\ \end{array} \]
- 平行法线分量
\[ \mathbf{R'}_{\parallel} = -\sqrt{1 - |\mathbf{R'}_{\bot}|^2} \mathbf{n} \]
Schlick 不等式估计反射的概率
- 近似菲涅尔项
\[ R(\theta) = R_0 + (1 - R_0)(1 - \cos \theta)^5 \]
\[ R_0=\left(\frac{n_1-n_2}{n_1+n_2}\right)^2 = \left(\dfrac{\dfrac{n_1}{n_2}-1}{\dfrac{n_1}{n_2}+1}\right)^2= \left(\dfrac{\dfrac{n_2}{n_1}-1}{\dfrac{n_2}{n_1}+1}\right)^2 \]
球的法向反向
- 半径设置为负数,这样可以让法相反向
- 因为我们在计算法相的时候,有一个除以半径的操作
8. 相机
- 相机参数,
y-z
平面
- lookfrom、lookat
- vup:用于表示相机的倾斜程度
- 从而建立起坐标系
1 | vec3 w = (lookfrom - lookat).unit_vector(); |
9. 透镜焦距效果
- defocus blur
- depth of field:景深
- focus distance
- the distance between the projection point and the plane where everything is in perfect focus
- controlled by the distance between the lens and the film/sensor
- focal length:焦距
- the distance between the projection point and the image plane
- aperture:光圈
- 大光圈 \(\to\) 高进光量、浅景深
薄透镜近似
- 我们不需要模拟内部结构,film 上的结果知识 focus plane 上物体的倒影罢了,因此我们可以直接对 focus plane 上的物体成像(二者是等价的)
- 也就是说,从透镜上采样即可
10. 结果图展示
spp
场景 1
- 1000spp
- 10000spp
场景 2
- 1spp
- 10spp
- 100spp
- 1000spp
最终结果
- 景深效果:1000spp
1 | point3 lookfrom(13, 2, 3); |
- 无景深效果:1000spp
11. 说明
OK
- 物体:球体
- 相机:任意位置
- 材质:diffuse、metal(glossy/specular)、dielectric
NO
- 光源
- 加速结构
- 三角面片