What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
上一修订版两侧同时换到之后的修订记录
cg:books:rt_one_wk:book_1 [2022/07/28 09:41] – [镜面反射] codingharecg:books:rt_one_wk:book_1 [2024/01/12 05:46] – [Ray Tracing In one Weekend] codinghare
行 1: 行 1:
-======Ray Tracing In one Weekend======+====Ray Tracing In one Weekend====
 //study notes// //study notes//
 ---- ----
行 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 &t^2*\underbrace{{\color{Peach} dot}(b,b)}_\text{a} +t*\underbrace{2*{\color{Peach} dot} (b,(A-C))}_\text{b} +\ +\Longrightarrow &t^2 \cdot \underbrace{{\color{Peach} \cdot}(b,b)}_\text{a} +t \cdot \underbrace{2 \cdot {\color{Peach} } (b,(A-C))}_\text{b} +\ 
-\underbrace{{\color{Peach} dot}((A-C),(A-C))-r^2}_\text{c} = 0 +\underbrace{{\color{Peach} \cdot}((A-C),(A-C))-r^2}_\text{c} = 0 
-\end{align}+\end{align*} 
 +\]
 ==具体实现== ==具体实现==
 可见的是,射线与球体是否相交的问题,就可以转变为关于 $t$ 的方程是否存在根的问题。这种情况下使用判别式 $b^2 -4ac$ 判断即可。\\ \\  可见的是,射线与球体是否相交的问题,就可以转变为关于 $t$ 的方程是否存在根的问题。这种情况下使用判别式 $b^2 -4ac$ 判断即可。\\ \\ 
行 646: 行 648:
 </code> </code>
 ===镜面反射=== ===镜面反射===
-与漫反射不同,光滑的金属产生的是镜面反射。镜面反射产生的射线方向与大小可由下图的关系计算出:+与漫反射不同,光滑的金属产生的是**镜面反射**(//Mirrored reflection//。镜面反射产生的射线方向与大小可由下图的关系计算出:
 \\ \\ \\  \\ \\ \\ 
 {{ :cg:books:rt_one_wk:fig-1.11-reflection.jpg?400 |}} {{ :cg:books:rt_one_wk:fig-1.11-reflection.jpg?400 |}}
行 652: 行 654:
 由图可知: 由图可知:
   * 镜面反射生成的射线方向为: $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) 
 +$$ 
 +实现: 
 +<code cpp> 
 +//in vec3.h 
 +vec3 reflect(const vec3& v, const vec3& n) { 
 +    return v - 2*dot(v,n)*n; 
 +
 +</code> 
 +==metal 类== 
 +''metal'' 类与 ''lambertain'' 类的结构类似,也需要重写 ''scatter'' 函数和添加衰减率的成员。与 ''lambertain'' 不同的是,''metal'' 生成的射线将按照镜面反射的规则来生成: 
 +<code cpp> 
 +class metal : public material { 
 +    public: 
 +        metal(const color& a) : albedo(a) {} 
 + 
 +        virtual bool scatter( 
 +            const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered 
 +        ) const override { 
 +            //scatter direction 
 +            vec3 reflected = reflect(unit_vector(r_in.direction()), rec.normal); 
 +            //scatter ray 
 +            scattered = ray(rec.p, reflected); 
 +            attenuation = albedo; 
 +            return (dot(scattered.direction(), rec.normal) > 0); 
 +        } 
 + 
 +    public: 
 +        color albedo; 
 +}; 
 +</code> 
 +===模糊镜面反射=== 
 +镜面反射的结果可以通过随机偏离反射射线的方向来进行模糊,达到一种类似**不光滑**表面金属的反射效果。我们将这种反射称为**模糊镜面反射**(//Fuzzy Reflection//)。反射射线方向的偏离实现与 //true lambertain// 类似,也是使用与相交点相切的单位球来生成随机的射线方向。 
 +\\ \\  
 +{{ :cg:books:rt_one_wk:fig-1.12-reflect-fuzzy.jpg?400 |}} 
 +\\ \\  
 +实现中,''metal'' 类添加了 ''fuzz'' 成员作为偏离的系数(越大越模糊)。该系数与 ''random_in_unit_sphere()'' 函数一起决定了反射射线最终的偏离量: 
 +<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()); 
 +</code> 
 +===main 文件中的对应修改[9.6]=== 
 +==ray_color()== 
 +由于我们已经将 material 抽象化,因此需要使用指针进行对应材质的调用。此处我们允许自行指定材质的衰减率: 
 +<code cpp> 
 + if (world.hit(r, 0.001, infinity, rec)) { 
 +        ray scattered; 
 +        color attenuation; 
 +        if (rec.mat_ptr->scatter(r, rec, attenuation, scattered)) 
 +            return attenuation * ray_color(scattered, world, depth-1); 
 +        return color(0,0,0); 
 +    } 
 +</code> 
 +<WRAP center round box 100%> 
 +之前一直不太明白为什么 ''scatter'' 都要返回一个 ''bool'',此处实际上给出了解答:**只有在反射射线与法线的方向同向的时候**,才会进行下一步的反射;否则将直接作为阴影处理。 
 +</WRAP> 
 +==场景的修改== 
 +  * 改变了背景大球的颜色 
 +  * 新增一左一右两球,材质为 metal 
 +  * 改变了中间球的颜色 
 +  * 模糊镜面反射版本需要提供额外的 ''fuzz'' 值 
 +<code cpp> 
 +auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0)); 
 +auto material_center = make_shared<lambertian>(color(0.7, 0.3, 0.3)); 
 +auto material_left   = make_shared<metal>(color(0.8, 0.8, 0.8)); 
 +auto material_right  = make_shared<metal>(color(0.8, 0.6, 0.2)); 
 + 
 +world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground)); 
 +world.add(make_shared<sphere>(point3( 0.0,    0.0, -1.0),   0.5, material_center)); 
 +world.add(make_shared<sphere>(point3(-1.0,    0.0, -1.0),   0.5, material_left)); 
 +world.add(make_shared<sphere>(point3( 1.0,    0.0, -1.0),   0.5, material_right)); 
 +</code>