图形学知识:Ray Tracing in a Weekend笔记

光线追踪读书笔记

Chapter 2:The vec3 class

  • 几乎所有的图形程序都有一些类用于存储几何向量和颜色。在许多系统中,这些向量是4D (3D +齐次坐标的几何,RGB + alpha透明通道的颜色)。对于我们的目的,三个坐标就足够了。我们将使用相同的类vec3用于颜色,位置,方向,偏移,等等。有些人不喜欢这个,因为它不能阻止你做一些愚蠢的事情,比如给一个位置添加颜色。他们有一个很好的观点,但当没有明显错误时,我们总是会采取“更少代码”的路线。
  • 下面是vec3类中的内容,后面还有一系列相关的内联函数就不记录下来了。
    在这里插入图片描述

Chapter 3: Rays, a simple camera, and background

  • 所有的射线追踪器都有一个射线类,以及沿着射线所看到的颜色的计算。我们把射线看成p (t) = A + t* B的函数。这里p是沿3D线的3D位置。A是射线原点B是射线方向。射线参数t是一个实数(在代码中为浮点数)。代入一个不同的t, p (t)沿着射线移动这个点。加上- t,就可以在3D线上任意移动。对于正t,你只得到A前面的部分,这就是通常所说的半线或射线。示例C = p(2)如下所示:
    在这里插入图片描述

  • 函数p (t)在更详细的代码形式中,我调用“point_at_parameter(t)”:
    在这里插入图片描述

  • 现在我们准备拐弯并制作一个射线追踪器。射线追踪器的核心是通过像素发送射线并计算在这些射线的方向上看到什么颜色。它的形式是计算**从眼睛到一个像素的光线,计算光线的交点,计算交点的颜色。**当我第一次开发光线追踪器时,我总是使用一个简单的摄像机来运行代码。我还创建了一个简单的color(ray)函数,用于返回背景的颜色(一个简单的渐变)。

  • 将“眼睛”(或者相机中心,如果你认为是相机)放在(0,0,0)y轴向上,x轴向右。为了遵守右手坐标系的惯例,进入屏幕的是负z轴。我将从左下角遍历屏幕,并沿着屏幕两侧使用两个偏移向量来移动光线端点。请注意,我没有将光线方向设置为单位长度向量,因为我认为这样做会使代码更简单、更快一些。
    在这里插入图片描述

  • 在下面的代码中,射线r将接近像素中心(我现在不担心准确性,因为我们稍后会添加抗锯齿):
    在这里插入图片描述

  • 颜色(射线)函数根据y坐标的上下方向线性混合白色和蓝色。我首先把它设为单位向量-1.0 < y < 1.0。然后我做了一个标准的图形技巧,将其缩放到0.0 < t < 1.0。当t=1.0时,我想要蓝色。当t = 0.0时,我想要白色。在这两者之间,我想要一个混合。这就形成了两者之间的“线性混合”,或者“线性插值”,或者简称为“lerp”。lerp总是这样的形式:blended_value = (1-t)start_value + tend_value, t从0到1。在我们的例子中,这会产生:

    在这里插入图片描述

Chapter 4: Adding a sphere

  • 人们经常在光线追踪器中使用球体,因为计算光线是否击中球体非常简单。以半径为R的原点为圆心的球面的方程是
    xx + yy + zz = RR

    你可能会注意到从中心C = (cx,cy,cz)到点p = (x,y,z)的向量是(p - C)。和点((p - C)、(p - C)) = (x-cx) * (x-cx) + (y-cy) * (y-cy) + (z-cz) * (z-cz)。所以球面的向量方程是:

    dot((p - c),(p - c)) = R*R

    我们可以把它理解为,球面上满足这个方程的任意点p。我们想知道射线p (t) = A + t* B是否击中球面。如果它确实击中了球面,有一个p (t)满足球面方程。所以我们需要观察哪里的t才是真的满足:

    dot((p (t) - c), (p (t) - c)) = R * R

    或扩大的完整形式射线p (t):

    dot((A + t * B - c), (A + t * B - c)) = R * R

    向量代数的规则下,如果我们展开这个方程把所有的项都移到左边我们得到:

    t*t*dot(​B​,​B​) + 2*t*dot(​B,A​-​C​) + dot(​A-C,A​-​C​) - R*R = 0

  • 方程中的向量和R都是已知的常数。未知量是t,方程是二次方程,就像你在高中数学课上看到的那样。你可以解出t,有一个平方根部分是正的(有两个实数解),负的(没有实数解)或零的(只有一个实数解)(B方-4AC)。
    在这里插入图片描述
    在这里插入图片描述

Chapter 5: Surface normals and multiple objects.

  • 让我们得到一个正常的表面,这样我们就可以许安然处阴影。这是一个垂直于曲面的向量,根据惯例,它指出。一个设计决策是这些法线(同样按照惯例)是否是单位长度。这对阴影很方便,所以我会说yes,但我不会在代码中强制它。这可能会出现一些细微的漏洞,所以请注意这只是个人偏好,就像大多数类似的设计决策一样。对于球体,法线方向是生命点减去圆心的方向:

    在这里插入图片描述

  • 现在让我们把它放到代码中,并给它添加阴影。我们还没有任何光线或其他东西,所以让我们用彩色地图来形象化法线。一种用来表示法线的常见技巧(因为假设N是一个单位长度的向量很容易,而且有点直观——所以每个分量都在-1和1之间)是将每个分量映射到从0到1的区间,然后将x/y/z映射到r/g/b。对于正常情况,我们需要命中点,而不仅仅是是否命中。让我们假设最近的点(最小t)。代码中的这些变化让我们可以计算和可视化N:

    在这里插入图片描述

  • 那么几个球体呢?虽然有一个球的数组很诱人,但一个非常干净的解决方案是为光线可能击中的任何东西创建一个“抽象类”,并使一个球和一个球的列表都是你可以击中的东西。这个类的名称有点模棱两可——如果不适合“面向对象”的编程,那么称它为“对象”就好了。“表面”是常用的,缺点是我们可能需要体积**。“可命中”强调的是将他们团结在一起的成员功能**。这些我都不喜欢,但我会选择“受欢迎的”。这个可命中的抽象类将有一个接收射线的命中函数。大多数射线追踪器发现将有效的tmin间隔添加到tmax是很方便的,所以只有在tmin < t < tmax时,命中才会“计数”。对于初始射线,这是正t,但正如我们将看到的,它可以帮助代码中的一些细节,使区间tmin到tmax。一个设计问题是,如果我们击中某个物体,是否需要计算正常值;在我们搜索的过程中,我们可能会找到更接近的东西,而我们只需要最接近的正常物体。我将使用简单的解决方案,并计算我将存储在某个结构中的东西。我知道我们在某些时候需要动态模糊,所以我将添加一个时间输入变量。下面是抽象类:
    在这里插入图片描述

  • 这是球面类(注意,我消去了一堆相互抵消的
    在这里插入图片描述

  • 和一个对象列表:
    在这里插入图片描述

Chapter 6: Antialiasing

  • 对相机类进行了抽象,我们需要的一件事是一个随机数生成器,它返回实数随机数。按照惯例返回0 <= ran < 1范围内的随机实数。1前面的“小于”很重要,因为我们有时会利用它 。
  • 对于一个给定的像素,我们在该像素内有几个样本,并向每个样本发送射线。然后将这些光线的颜色平均
    在这里插入图片描述
    把所有这些放在一起就会生成一个相机类,它封装了我们之前的简单的轴向相机:
    在这里插入图片描述

Chapter 7: Diffuse Materials

  • 我们将使用单独的渲染器——这在大多数渲染器中很常见——但要注意其局限性。不发光的漫反射物体只是呈现出其周围环境的颜色,但它们会用自身固有的颜色来调节这种颜色。从漫射表面反射的光的方向是随机的。所以,如果我们向两个扩散表面之间的裂纹发射三束射线,它们将有不同的随机行为:
    在这里插入图片描述
    也可能被吸收而不是反映出来。表面越暗,越容易被吸收。实际上,任何随机化方向的算法都会产生看起来粗糙的表面。其中一个最简单的方法被证明是完全正确的理想漫反射表面
    从单位半径球面上选择一个与生命点相切的随机点s,从生命点p发送一条射线到随机点s。圆心为(p + N)

    在这里插入图片描述

  • 我们还需要一种在以原点为中心的单位半径球面上随机选取一个点的方法。我们将使用通常最简单的算法:拒绝法。首先,我们在单位立方体中随机选择一个点,其中x、y和z的范围都在-1到+1之间。我们拒绝这个点,如果这个点在球面外,我们再试一次。do/while结构非常适合:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值