本 Wiki 开启了 HTTPS。但由于同 IP 的 Blog 也开启了 HTTPS,因此本站必须要支持 SNI 的浏览器才能浏览。为了兼容一部分浏览器,本站保留了 HTTP 作为兼容。如果您的浏览器支持 SNI,请尽量通过 HTTPS 访问本站,谢谢!
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录前一修订版后一修订版 | 前一修订版后一修订版两侧同时换到之后的修订记录 | ||
cg:books:rt_one_wk:book_1 [2022/07/28 09:44] – [镜面反射] codinghare | cg:books:rt_one_wk:book_1 [2023/11/27 08:14] – [数学原理以及推导] codinghare | ||
---|---|---|---|
行 132: | 行 132: | ||
现在利用点积的结合律对该等式进行扩展,我们可以得到一个关于 $t$ 的一元二次方程: | 现在利用点积的结合律对该等式进行扩展,我们可以得到一个关于 $t$ 的一元二次方程: | ||
\\ \\ | \\ \\ | ||
- | \begin{align} | + | \[ |
+ | \begin{align*} | ||
&dot((A + tb -C), (A + tb -C)) = r^2 \newline | &dot((A + tb -C), (A + tb -C)) = r^2 \newline | ||
\Longrightarrow &dot(tb + {\color{Red}(A-C) }), (tb + {\color{Red}(A-C) }) = r^2 \newline | \Longrightarrow &dot(tb + {\color{Red}(A-C) }), (tb + {\color{Red}(A-C) }) = r^2 \newline | ||
\Longrightarrow & | \Longrightarrow & | ||
\underbrace{{\color{Peach} dot}((A-C), | \underbrace{{\color{Peach} dot}((A-C), | ||
- | \end{align} | + | \end{align*} |
+ | \] | ||
==具体实现== | ==具体实现== | ||
可见的是,射线与球体是否相交的问题,就可以转变为关于 $t$ 的方程是否存在根的问题。这种情况下使用判别式 $b^2 -4ac$ 判断即可。\\ \\ | 可见的是,射线与球体是否相交的问题,就可以转变为关于 $t$ 的方程是否存在根的问题。这种情况下使用判别式 $b^2 -4ac$ 判断即可。\\ \\ | ||
行 646: | 行 648: | ||
</ | </ | ||
===镜面反射=== | ===镜面反射=== | ||
- | 与漫反射不同,光滑的金属产生的是镜面反射。镜面反射产生的射线方向与大小可由下图的关系计算出: | + | 与漫反射不同,光滑的金属产生的是**镜面反射**(// |
\\ \\ \\ | \\ \\ \\ | ||
{{ : | {{ : | ||
行 653: | 行 655: | ||
* 镜面反射生成的射线方向为: $v + 2 \cdot b$ | * 镜面反射生成的射线方向为: $v + 2 \cdot b$ | ||
* 镜面反射射线的 magnitude 为:$-v \cdot n$ | * 镜面反射射线的 magnitude 为:$-v \cdot n$ | ||
- | 因此该射线可以表示为: | + | 依据点积的结合律,该射线可以表示为: |
$$ | $$ | ||
v + 2 * dot(-v, n) \Longrightarrow v - 2 *dot(v, n) | v + 2 * dot(-v, n) \Longrightarrow v - 2 *dot(v, n) | ||
$$ | $$ | ||
+ | 实现: | ||
+ | <code cpp> | ||
+ | //in vec3.h | ||
+ | vec3 reflect(const vec3& v, const vec3& n) { | ||
+ | return v - 2*dot(v, | ||
+ | } | ||
+ | </ | ||
+ | ==metal 类== | ||
+ | '' | ||
+ | <code cpp> | ||
+ | class metal : public material { | ||
+ | public: | ||
+ | metal(const color& a) : albedo(a) {} | ||
+ | |||
+ | virtual bool scatter( | ||
+ | const ray& r_in, const hit_record& | ||
+ | ) const override { | ||
+ | //scatter direction | ||
+ | vec3 reflected = reflect(unit_vector(r_in.direction()), | ||
+ | //scatter ray | ||
+ | scattered = ray(rec.p, reflected); | ||
+ | attenuation = albedo; | ||
+ | return (dot(scattered.direction(), | ||
+ | } | ||
+ | |||
+ | public: | ||
+ | color albedo; | ||
+ | }; | ||
+ | </ | ||
+ | ===模糊镜面反射=== | ||
+ | 镜面反射的结果可以通过随机偏离反射射线的方向来进行模糊,达到一种类似**不光滑**表面金属的反射效果。我们将这种反射称为**模糊镜面反射**(// | ||
+ | \\ \\ | ||
+ | {{ : | ||
+ | \\ \\ | ||
+ | 实现中,'' | ||
+ | <code cpp> | ||
+ | //cstr | ||
+ | metal(const color& a, double f) : albedo(a), fuzz(f < 1 ? f : 1) {} | ||
+ | //scattered ray with fuzzy reflection | ||
+ | scattered = ray(rec.p, reflected + fuzz*random_in_unit_sphere()); | ||
+ | </ | ||
+ | ===main 文件中的对应修改[9.6]=== | ||
+ | ==ray_color()== | ||
+ | 由于我们已经将 material 抽象化,因此需要使用指针进行对应材质的调用。此处我们允许自行指定材质的衰减率: | ||
+ | <code cpp> | ||
+ | if (world.hit(r, | ||
+ | ray scattered; | ||
+ | color attenuation; | ||
+ | if (rec.mat_ptr-> | ||
+ | return attenuation * ray_color(scattered, | ||
+ | return color(0, | ||
+ | } | ||
+ | </ | ||
+ | <WRAP center round box 100%> | ||
+ | 之前一直不太明白为什么 '' | ||
+ | </ | ||
+ | ==场景的修改== | ||
+ | * 改变了背景大球的颜色 | ||
+ | * 新增一左一右两球,材质为 metal | ||
+ | * 改变了中间球的颜色 | ||
+ | * 模糊镜面反射版本需要提供额外的 '' | ||
+ | <code cpp> | ||
+ | auto material_ground = make_shared< | ||
+ | auto material_center = make_shared< | ||
+ | auto material_left | ||
+ | auto material_right | ||
+ | |||
+ | world.add(make_shared< | ||
+ | world.add(make_shared< | ||
+ | world.add(make_shared< | ||
+ | world.add(make_shared< | ||
+ | </ | ||
+ |