Light

We’ll start adding “realism” to our rendering of the scene by introducing light. Light is a vast and complex topic, so we’ll present a simplified model that is good enough for our purposes. This model is, for the most part, inspired by how light works in the real world, but it also takes some liberties with the aim of making the rendered scenes look good.
我们将通过引入光线开始为我们的场景渲染添加 "真实感"。光线是一个广泛而复杂的话题,所以我们将介绍一个简化的模型,它对我们的目的来说已经足够好了。这个模型在很大程度上是受光线在现实世界中如何工作的启发,但它也有一些自由度,目的是使渲染的场景看起来不错。

We’ll start with some simplifying assumptions that will make our lives easier, then we’ll introduce three types of light sources: point lights, directional lights, and ambient light. We’ll end the chapter by discussing how these lights affect the appearance of surfaces, including diffuse and specular reflection.
我们将从一些简化的假设开始,这将使我们的生活更容易,然后我们将介绍三种类型的光源:点光源、方向性光源和环境光。在本章的最后,我们将讨论这些灯光如何影响表面的外观,包括漫反射和镜面反射。

Simplifying Assumptions 简化假设

Let’s make a few assumptions to make things simpler. First, we declare that all light is white. This lets us characterize any light using a single real number, i, called the intensity of the light. Simulating colored lights isn’t that complicated (we’d just use three intensity values, one per color channel, and compute all color and lighting channel-wise), but we’ll stick to white lights to keep things simple.
让我们做一些假设,使事情变得简单些。首先,我们宣布,所有的光都是白色的。这让我们可以用一个单一的实数i𝑖来描述任何光线的特征,这个数字被称为光线的强度。模拟彩色灯光并不复杂(我们只需使用三个强度值,每个颜色通道一个,并按通道计算所有的颜色和光照),但我们将坚持使用白色灯光以保持事情的简单性。

Second, we’ll ignore the atmosphere. In real life, lights look dimmer the farther away they are; this is because of particles floating in the air that absorb part of the light as it travels through them. While this isn’t particularly complicated to do in a raytracer, we’ll keep it simple and ignore this effect; in our scene, distance doesn’t make lights any less bright.
第二,我们将忽略大气层。在现实生活中,灯光看起来越远越暗;这是因为漂浮在空气中的粒子在光线穿过它们的时候会吸收一部分。虽然这在光线跟踪器中并不特别复杂,但我们将保持简单,忽略这一效果;在我们的场景中,距离并不会使灯光变得更暗。

Light Sources 光源

Light has to come from somewhere. In this section, we’ll define three different types of light sources.
光必须来自某处。在本节中,我们将定义三种不同类型的光源。

Point Lights 点灯

Point lights emit light from a fixed point in 3D space, called their position. They emit light equally in every direction; this is why they are also called omnidirectional lights. A point light is therefore fully described by its position and its intensity.
点光源是从三维空间中的一个固定点发出的光,称为其位置。它们在每个方向上都发出同样的光;这就是为什么它们也被称为全向光。因此,一个点光源完全由其位置和强度来描述。

A light bulb is a good real-life approximation of a point light. While a real-life light bulb doesn’t emit light from a single point, and it isn’t perfectly omnidirectional, it’s a pretty accurate approximation.
灯泡是一个很好的现实生活中的点光源的近似值。虽然现实生活中的灯泡并不是从一个点发光,也不是完全全向的,但它是一个相当准确的近似值。

Let’s define the vector L as the direction from a point in the scene, P, to the light, Q. We can calculate this vector, called the light vector, as QP. Note that since Q is fixed but P can be any point in the scene, L is different for every point in the scene, as you can see in Figure 3-1.
让我们定义矢量L ⃗ 𝐿 →作为从场景中的一个点P 𝑃到光线Q 𝑄的方向。我们可以计算这个矢量,称为光矢量,即Q-P 𝑄 - 𝑃。请注意,由于Q𝑄是固定的,但P𝑃可以是场景中的任何一点,所以L⃗𝐿→对于场景中的每一点都是不同的,如图3-1所示。

Figure 3-1: A point light at Q. The \vec{\mathsf{L\}\} vector is different for every point P.

Directional Lights 方向灯

If a point light is a good approximation of a light bulb, does it also work as an approximation of the Sun?
如果一个点光源可以很好地近似于一个灯泡,那么它是否也可以近似于太阳?

This is a tricky question, and the answer depends on what we are trying to render. At the solar-system scale, the Sun can be approximated as a point light. After all, it emits light from a point, and it emits in all directions, so it seems to qualify.
这是一个棘手的问题,答案取决于我们试图呈现的内容。在太阳系的范围内,太阳可以被近似地看作是一个点光源。毕竟,它从一个点发出的光,而且它向所有方向发射,所以它似乎符合条件。

However, if our scene represents something happening on Earth, it’s not such a good approximation. The Sun is so far away that every ray of light that reaches us has almost exactly the same direction. We could approximate this with a point light located very, very, very far away from the objects in the scene. However, the distance between the light and the objects would be orders of magnitude greater than the distance between objects, so we’d start running into numerical accuracy errors.
然而,如果我们的场景代表了地球上发生的事情,那就不是那么好的近似了。太阳是如此之远,以至于到达我们这里的每一束光都有几乎完全相同的方向。我们可以用一个离场景中的物体非常、非常、非常远的点光源来近似。然而,光和物体之间的距离会比物体之间的距离大几个数量级,所以我们会开始遇到数字精度误差。

To better handle these situations, we define directional lights. Like point lights, directional lights have an intensity, but unlike them, they don’t have a position; instead, they have a fixed direction. You can think of them as infinitely distant point lights located in the specified direction.
为了更好地处理这些情况,我们定义了方向性灯光。和点光源一样,定向灯也有一个强度,但和它们不同的是,它们没有一个位置;相反,它们有一个固定的方向。你可以把它们看作是位于指定方向上的无限远的点灯。

While in the case of point lights we need to compute a different light vector L for every point P in the scene, in this case L is given. In the Sun-to-Earth scene example, L would be (center of Sun) – (center of Earth). Figure 3-2 shows what this looks like.
而在点光源的情况下,我们需要为场景中的每一个点P𝑃计算不同的光矢量L⃗ 𝐿 →,在这种情况下,L⃗ 𝐿 →是给定的。在太阳到地球的场景例子中,L ⃗ 𝐿 → 将是(太阳的中心)-(地球的中心)。图3-2显示了这是什么样子。

Figure 3-2: A directional light. The \vec{\mathsf{L\}\} vector is the same for every point P.

As we can see here, the light vector of a directional light is the same for every point in the scene. Compare this with Figure 3-1, where the light vector of a point light is different for every point in the scene.
正如我们在这里看到的,定向灯的光矢量对场景中的每一个点都是一样的。与图3-1相比,点光源的光矢量对场景中的每个点都是不同的。

Ambient Light 环境光

Can every real-life light be modeled as a point or directional light? Pretty much. Are these two types of light enough to light a scene? Unfortunately not.
每一个现实生活中的灯光都可以被模拟成点光源或方向性光源吗?差不多是这样。这两种类型的光足以照亮一个场景吗?可惜不是。

Consider what happens to the Moon. The only significant light source nearby is the Sun. So the “front half” of the Moon with respect to the Sun gets all its light, and its “back half” is in complete darkness. We see this from different angles from Earth, creating what we call the “phases” of the Moon.
考虑一下发生在月球上的事情。附近唯一重要的光源是太阳。因此,月球相对于太阳的 "前半部分 "获得了所有的光线,而它的 "后半部分 "则完全处于黑暗之中。我们从地球上的不同角度看到这种情况,形成了我们所说的月球的 "相位"。

However, the situation down here on Earth is a bit different. Even points that don’t receive light directly from a light source aren’t completely in the dark (just look at the floor under your chair). How do rays of light reach these points if their “view” of the light sources is obstructed by something else?
然而,地球上的情况却有点不同。即使是那些没有直接从光源接受光线的点也不是完全处于黑暗之中(看看你椅子下的地板就知道了)。如果光源的 "视野 "被其他东西阻挡,那么光线如何到达这些点呢?

As mentioned in “Color Models” in Chapter 1 (Introductory Concepts), when light hits an object, part of it is absorbed, but the rest is scattered back into the scene. This means that light can come not only from light sources, but also from objects that get light from light sources and scatter part of it back into the scene. But why stop there? The scattered light will in turn hit some other object, part of it will be absorbed, and part of it will be scattered back into the scene. And so on, until all of the energy of the original light has been absorbed by the surfaces in the scene.
正如第一章(概念介绍)中的 "颜色模型 "所提到的,当光线照射到物体上时,一部分会被吸收,但剩下的会散射回场景中。这意味着光不仅可以来自于光源,也可以来自于那些从光源获得光线并将部分光线散射回场景的物体。但为什么要止步于此呢?散射的光线又会打到其他物体上,一部分被吸收,一部分又被散射回场景中。以此类推,直到原始光线的所有能量都被场景中的表面所吸收。

This means we should treat every object as a light source. As you can imagine, this would add a lot of complexity to our model, so we won’t explore that mechanism in this book. If you’re curious, search for global illumination and marvel at the pretty pictures.
这意味着我们应该把每个物体都当作一个光源。你可以想象,这将给我们的模型增加很多复杂性,所以我们不会在本书中探讨这种机制。如果你感到好奇,可以搜索一下全局照明,并对那些漂亮的图片感到惊叹。

But we still don’t want every object to be either directly illuminated or completely dark (unless we’re actually rendering a model of the solar system). To overcome this limitation, we’ll define a third type of light source, called ambient light, which is characterized only by its intensity. We’ll declare that an ambient light contributes some light to every point in the scene, regardless of where it is. It’s a gross oversimplification of the very complex interaction between the light sources and the surfaces in the scene, but it works well enough.
但是我们仍然不希望每个物体都被直接照亮或者完全黑暗(除非我们真的要渲染一个太阳系的模型)。为了克服这个限制,我们将定义第三种类型的光源,叫做环境光,它的特点是只有强度。我们将声明,环境光对场景中的每一个点都贡献了一些光,不管它在哪里。这是对场景中光源和表面之间非常复杂的相互作用的过度简化,但它的效果足够好。

In general, a scene will have a single ambient light (because ambient lights only have an intensity value, any number of them can be trivially combined into a single ambient light) and an arbitrary number of point and directional lights.
一般来说,一个场景会有一个单一的环境光(因为环境光只有一个强度值,任何数量的环境光都可以简单地组合成一个环境光)和任意数量的点光源和定向光。

Illumination of a Single Point
单个点的照明

Now that we know how to define the lights in a scene, we need to figure out how the lights interact with the surfaces of the objects in the scene.
现在我们知道了如何定义场景中的灯光,我们需要弄清楚灯光如何与场景中的物体表面互动。

In order to compute the illumination of a single point, we’ll compute the amount of light contributed by each light source and add them together to get a single number representing the total amount of light the point receives. We can then multiply the color of the surface at that point by this amount to get the shade of color that represents how much light it receives.
为了计算一个点的照度,我们要计算每个光源所贡献的光量,然后把它们加在一起,得到一个代表该点接受的总光量的数字。然后,我们可以用该点的表面颜色乘以这个数字,得到代表该点接受多少光的颜色。

So, what happens when a ray of light, be it from a directional light or a point light, hits a point on some object in our scene?
那么,当一束光,无论是来自定向光还是点光源,击中我们场景中某个物体上的某个点时,会发生什么?

We can intuitively classify objects into two broad classes, depending on how they reflect light: “matte” and “shiny” objects. Since most objects around us can be classified as matte, we’ll focus on this group first.
我们可以凭直觉将物体分为两大类,这取决于它们如何反射光线:"哑光 "和 "亮光 "物体。由于我们周围的大多数物体都可以被归类为亚光,我们将首先关注这一组。

Diffuse Reflection 漫反射

When a ray of light hits a matte object, the ray is scattered back into the scene equally in every direction, a process called diffuse reflection; this is what makes matte objects look matte.
当一束光线照射到消光物体上时,光线会向各个方向平等地散射回场景中,这个过程称为漫反射;这就是使消光物体看起来像消光的原因。

To verify this, look at some matte object around you, such as a wall. If you move with respect to the wall, its color doesn’t change. That is, the light you see reflected from the object is the same no matter where you’re looking from.
为了验证这一点,请看你周围的一些哑光物体,比如说一堵墙。如果你相对于墙壁移动,其颜色不会改变。也就是说,无论你从哪里看,你看到的物体反射的光线都是一样的。

On the other hand, the amount of light reflected does depend on the angle between the ray of light and the surface. Intuitively, this happens because the energy carried by the ray has to spread over a smaller or bigger area depending on the angle, so the energy reflected to the scene per unit of area is higher or lower, respectively, as shown in Figure 3-3.
另一方面,光线的反射量确实取决于光线和表面之间的角度。直观地讲,发生这种情况是因为光线携带的能量要根据角度分散到更小或更大的区域,所以反射到场景中的单位面积的能量分别较高或较低,如图3-3所示。

Figure 3-3: The energy of a ray of light spreads over areas of different size, depending on its angle to the surface.

In Figure 3-3, we can see two rays of light of the same intensity (represented by having the same width) hitting a surface head-on and at an angle. The energy carried by the rays of light spreads uniformly across the areas they hit. The energy of the ray on the right spreads across a bigger area than that of the ray on the left, and therefore each point in its area receives less energy than in the left-hand case.
在图3-3中,我们可以看到两道强度相同的光线(表示为具有相同的宽度)以一定的角度正面击中一个表面。光线所携带的能量均匀地扩散到它们所撞击的区域。右边那条光线的能量比左边那条光线的能量在更大的区域内传播,因此其区域内的每一个点得到的能量都比左边的情况少。

To explore this mathematically, let’s characterize the orientation of a surface by its normal vector. The normal vector of a surface at point P, or simply “the normal,” is a vector perpendicular to the surface at P. It’s also a unit vector, meaning its length is 1. We’ll call this vector N.
为了从数学上探讨这个问题,让我们用法线向量来描述一个曲面的方向。一个表面在P𝑃点的法向量,或者简单地说 "法向",是一个垂直于P𝑃点的表面的向量。它也是一个单位向量,意味着它的长度是11。我们把这个向量称为N⃗𝑁→。

Modeling Diffuse Reflection 漫反射建模

A ray of light with direction L and intensity I hits a surface with normal N. What fraction of I is reflected back to the scene, as a function of I, N, and L?
一束方向为L⃗ 𝐿 →、强度为I𝐼的光线射到法线为N⃗ 𝑁 →的表面。作为I𝐼、N⃗𝑁→和L⃗𝐿→的函数,I𝐼被反射回场景的部分是多少?

As a geometric analogy, let’s represent the intensity of the light as the “width” of the ray. Its energy spreads over a surface of size A. When N and L have the same direction—when the ray is perpendicular to the surface—then I=A, which means the energy reflected per unit of area is the same as the incident energy per unit of area: IA=1. On the other hand, as the angle between L and N approaches 90, A approaches , so the energy per unit of area approaches 0; limAIA=0. But what happens in between?
作为一个几何类比,让我们把光的强度表示为光线的 "宽度"。它的能量散布在一个大小为A𝐴的表面上。当N ⃗ 𝑁 →和L ⃗ 𝐿 →有相同的方向--当光线垂直于表面时,I=A 𝐼 = 𝐴,这意味着每单位面积反射的能量与每单位面积入射的能量相同。I A =1 𝐼 𝐴 = 1。另一方面,当L ⃗ 𝐿 →与N ⃗ 𝑁 →之间的角度接近90 ∘90 ∘时,A 𝐴接近∞,所以单位面积的能量接近0;lim A→∞ I A =0 lim 𝐴 → ∞ 𝐼 𝐴 =0。但在这之间会发生什么?

The situation is depicted in Figure 3-4. We know N, L, and P ; I have added the angles α and β, and the points Q, R, and S to make writing about the diagram easier.
这种情况在图3-4中描述。我们知道N⃗𝑁→,L⃗𝐿→,P𝑃;我加上了角α𝛼和β𝛽,以及点Q𝑄,R𝑅和S𝑆,以便于写图。

Figure 3-4: The vectors and angles involved in the diffuse reflection calculations

Since a ray of light technically has no width, we can assume that everything happens in a flat, infinitesimally small patch of the surface. Even if it’s the surface of a sphere, the area we’re considering is so infinitesimally small that it’s almost flat in comparison with the size of the sphere, just like Earth looks flat at small scales.
由于一束光在技术上没有宽度,我们可以假设一切都发生在一个平坦的、无限小的表面上。即使是球体的表面,我们所考虑的区域也是无限小的,与球体的大小相比,它几乎是平的,就像地球在小范围内看起来是平的。

The ray of light, with a width of I, hits the surface at P, at an angle β. The normal at P is N, and the energy carried by the ray spreads over A. We need to compute IA.
光线的宽度为I𝐼,在P𝑃处击中表面,角度为β𝛽。P𝑃处的法线是N⃗𝑁→,射线携带的能量在A𝐴处扩散。我们需要计算I A 𝐼 𝐴。

Consider RS, the “width” of the ray. By definition, it’s perpendicular to L, which is also the direction of PQ. Therefore, PQ and QR form a right angle, making PQR a right triangle.
考虑RS 𝑅 𝑆,即射线的 "宽度"。根据定义,它垂直于L ⃗ 𝐿 →,这也是PQ 𝑃 𝑄的方向。因此,PQ 𝑃 𝑄和QR 𝑄 𝑅形成一个直角,使PQR 𝑃 𝑅成为一个直角三角形。

One of the angles of PQR is 90, and another is β. The remaining angle is therefore 90β. But note that N and PR also form a right angle, which means α+β must also be 90. Therefore, QRP^=α.
PQR 𝑃 𝑄 𝑅的一个角是90 ∘ 90 ∘,另一个角是 β 𝛽。因此,剩下的角度是90 ∘ -β 90 ∘ - 𝛽。但请注意,N ⃗ 𝑁 → 和PR 𝑃 𝑅也形成一个直角,这意味着α+β 𝛼 + 𝛽也必须是 90 ∘ 90 ∘。因此,QRPˆ=α 𝑄 𝑅 𝑃 ^ = 𝛼。

Let’s focus on the triangle PQR (Figure 3-5). Its angles are α, β, and 90. The side QR measures I2, and the side PR measures A2.
让我们来关注一下三角形PQR 𝑃 𝑄 𝑅(图3-5)。其角度为α 𝛼,β 𝛽,90 ∘90 ∘。边QR𝑄𝑅的尺寸为I 2 𝐼 2,边PR𝑃𝑅的尺寸为A 2 𝐴 2。

Figure 3-5: The PQR triangle in a trigonometry context

And now, trigonometry to the rescue! By definition, cos(α)=QRPR; substituting QR with I2 and PR with A2, we get
现在,三角学来救场了!根据定义,cos(α)=QR PR 𝑐 𝑜 𝑠 ( 𝛼 ) = 𝑄 𝑅 𝑃 𝑅;用I 2 𝐼 2代替QR 𝑄 𝑅,用A 2 𝐴 2代替PR 𝑃 𝑅,我们得到

cos(α)=I2A2

which becomes 即成为

cos(α)=IA

We’re almost there. α is the angle between N and L. We can use the properties of the dot product (feel free to consult the Linear Algebra appendix) to express cos(α) as
α𝛼是N⃗𝑁→与L⃗𝐿→之间的角度。我们可以利用点积的特性(请随时查阅线性代数附录)来表示cos(α) 𝑐 𝑜 𝑠 ( 𝛼 ) 为

cos(α)=N,L|N||L|
cos(α)= ⟨ N ⃗ , L ⃗ ⟩ | N ⃗ || L ⃗ | 𝑐 𝑜 𝑠 ( 𝛼 ) = ⟨ 𝑁 → , 𝐿 → ⟩ | | 𝐿 → |

And finally 而最后

IA=N,L|N||L|
i a = ⟨ n ⃗ , l ⃗ ⟩ | n ⃗ || l ⃗ | 𝐼 𝐴 = ⟨ 𝑁 → , 𝐿 → , 𝑁 → | 𝐿 →

We have arrived at a simple equation that gives us the fraction of light that is reflected as a function of the angle between the surface normal and the direction of the light.
我们已经得出了一个简单的方程式,它给出了作为表面法线和光的方向之间的角度的函数的反射的光的分数。

Note that the value of cos(α) becomes negative for angles over 90. If we blindly use this value, we can end up with a light source that makes a surface darker! This doesn’t make any physical sense; an angle over 90 just means the light is actually illuminating the back of the surface, and therefore it doesn’t contribute any light to the point we’re illuminating. So if cos(α) becomes negative, we need to treat it as if it was 0.
请注意,cos(α) 𝑐 𝑜 𝑠 ( 𝛼 )的值在超过90∘的角度时会变成负值。如果我们盲目地使用这个数值,我们最终会得到一个使表面变暗的光源!这在物理上是没有意义的。这没有任何物理意义,超过90∘的角度只是意味着光线实际上照到了表面的背面,因此它对我们要照到的点没有贡献任何光线。所以如果cos(α) 𝑐 𝑜 𝑠 ( 𝛼 )变成负数,我们需要把它当作0 0。

The Diffuse Reflection Equation
漫反射方程

We can now formulate an equation to compute the full amount of light received by a point P with normal N in a scene with an ambient light of intensity IA and n point or directional lights with intensity In and light vectors Ln either known (for directional lights) or computed for P (for point lights):
现在我们可以列一个方程来计算一个法线为 N⃗ 𝑁 → 的点 P 𝑃 在一个环境光强度为 I A 𝐼 𝐴 的场景中所接受的全部光量。𝑛的点光源或定向光源,其强度为 I n 𝐼 𝑛,光矢量为 L n → 𝐿 𝑛 → 已知(对于定向光源)或为 P 𝑃 计算(对于点光源)。

IP=IA+i=1nIiN,Li|N||Li|
I P = I A + ∑ i=1 n I i ⟨ N ⃗ , L i → ⟩ | N ⃗ || L i → | 𝐼 𝑃 = 𝐼 𝐴 + ∑ 𝑖 = 1 𝑛 𝐼 ⟨ 𝑁 →, 𝐿 𝑖 → ⟩ | 𝑁 → | 𝐿 𝑖 → |

It’s worth repeating that the terms where N,Li<0 shouldn’t be added to the point’s illumination.
值得重申的是,当⟨ N ⃗ , L i → ⟩<0 𝑁 → , 𝐿 𝑖 → ⟩ < 0 的条款不应加入到点的照明中。

Sphere Normals 球体法线

There’s only a small detail missing: where do the normals come from? The answer to this general question is far more complex than it might seem, as we’ll see in the second part of this book. Fortunately, at this point we’re only dealing with spheres, and there’s a very simple answer for them: the normal vector of any point of a sphere lies on a line that goes through the center of the sphere. As you can see in Figure 3-6, if the sphere center is C, the direction of the normal at point P is PC.
只缺少一个小细节:法线从哪里来?这个一般问题的答案比它看起来要复杂得多,我们将在本书的第二部分看到。幸运的是,在这一点上我们只处理球体,对于球体有一个非常简单的答案:球体上任何一点的法线向量都位于一条穿过球体中心的直线上。正如你在图3-6中看到的,如果球心是C 𝐶,那么P𝑃点的法线方向就是P-C 𝑃 - 𝐶。

Figure 3-6: The normal of a sphere at P has the same direction as CP.

Why “the direction of the normal” and not “the normal”? A normal vector needs to be perpendicular to the surface, but it also needs to have length 1. To normalize this vector and turn it into a true normal, we need to divide it by its own length, thus guaranteeing the result has length 1:
为什么是 "法线的方向 "而不是 "法线"?一个法线矢量需要与表面垂直,但它也需要有长度11。为了将这个向量归一化,变成真正的法线,我们需要用它自己的长度来除以它,从而保证结果的长度为1 1。

N=PC|PC|
n ⃗ = p-c |p-c| 𝑁 → = 𝑃 - 𝐶 | 𝑃 - 𝐶

Rendering with Diffuse Reflection
使用漫反射进行渲染

Let’s translate all of this to pseudocode. First, let’s add a couple of lights to the scene:
让我们把这些都转化为伪代码。首先,让我们在场景中添加几个灯。

light {
    type = ambient
    intensity = 0.2
}
light {
    type = point
    intensity = 0.6
    position = (2, 1, 0)
}
light {
    type = directional
    intensity = 0.2
    direction = (1, 4, 4)
}

Note that the intensities conveniently add up to 1.0; because of the way the lighting equation works, this ensures that no point can have a light intensity greater than this value. This means we won’t have any “overexposed” spots.
请注意,这些强度的总和是1.0 1.0;由于照明方程的工作方式,这确保了任何一个点的光照强度都不会大于这个值。这意味着我们不会有任何 "曝光过度 "的点。

The lighting equation is fairly straightforward to translate to pseudocode (Listing 3-1).
照明方程式是相当直接的,可以转化为伪代码(清单3-1)。

ComputeLighting(P, N) {
    i = 0.0
    for light in scene.Lights {
        if light.type == ambient {
           ❶i += light.intensity
        } else {
            if light.type == point {
               ❷L = light.position - P
            } else {
               ❸L = light.direction
            }

            n_dot_l = dot(N, L)
           ❹if n_dot_l > 0 {
               ❺i += light.intensity * n_dot_l/(length(N) * length(L))
            }
        }
    }
    return i
}
Listing 3-1: A function to compute lighting with diffuse reflection
清单3-1:一个计算漫反射照明的函数

In Listing 3-1, we treat the three types of light in slightly different ways. Ambient lights are the simplest and are handled directly ❶. Point and directional lights share most of the code, in particular the intensity calculation ❺, but the direction vectors are computed in different ways (❷ and ❸), depending on their type. The condition in ❹ makes sure we don’t add negative values, which represent lights illuminating the back side of the surface, as we discussed before.
在清单 3-1 中,我们以稍微不同的方式处理这三种类型的光。环境光是最简单的,直接被处理 ❶。点光源和定向光源共享大部分代码,特别是强度计算 ❺,但方向向量的计算方式不同(❷和❸),取决于它们的类型。❶中的条件确保我们不会添加负值,这代表照亮表面背面的灯光,正如我们之前讨论过的。

The only thing left to do is to use ComputeLighting in TraceRay. We replace the line that returns the color of the sphere:
唯一要做的是在 TraceRay 中使用 ComputeLighting 。我们替换掉返回球体颜色的那一行。

return closest_sphere.color

with this snippet: 与这个片段。

P = O + closest_t * D  // Compute intersection
N = P - closest_sphere.center  // Compute sphere normal at intersection
N = N / length(N)
return closest_sphere.color * ComputeLighting(P, N)

Just for fun, let’s add a big yellow sphere:
只是为了好玩,让我们添加一个大的黄色球体。

sphere {
    color = (255, 255, 0)  # Yellow
    center = (0, -5001, 0)
    radius = 5000
}

We run the renderer and, lo and behold, the spheres now start to look like spheres (Figure 3-7)!
我们运行渲染器,看啊,球体现在开始像球体了(图3-7)。

Figure 3-7: Diffuse reflection adds a sense of depth and volume to the scene.

Source code and live demo >>
源代码和现场演示 >>

But wait, how did the big yellow sphere turn into a flat yellow floor? It hasn’t; it’s just so big compared to the other three spheres, and the camera is so close to it, that it looks flat—just like the surface of our planet looks flat when we’re standing on it.
但是,等等,那个黄色的大球体怎么会变成一个平坦的黄色地板呢?它没有;与其他三个球体相比,它只是太大,而且摄像机离它太近,所以它看起来很平--就像我们站在地球上时,地球表面看起来很平。

Specular Reflection 镜面反射

Let’s turn our attention to shiny objects. Unlike matte objects, shiny objects look slightly different depending on where you’re looking from.
让我们把注意力转向有光泽的物体。与哑光物体不同,有光泽的物体看起来略有不同,这取决于你从哪里看。

Imagine a billiard ball or a car just out of the car wash. These kinds of objects exhibit very specific light patterns, usually bright spots, that seem to move as you move around them. Unlike matte objects, the way you perceive the surface of these objects does actually depend on your point of view.
想象一下一个台球或一辆刚从洗车房出来的汽车。这些类型的物体表现出非常具体的光照模式,通常是亮斑,当你在它们周围移动时,它们似乎会移动。与哑光物体不同,你对这些物体表面的感知方式实际上取决于你的视角。

Note that a red billiard ball stays red if you walk around it, but the bright white spot that gives it its shiny appearance moves as you do. This shows that the new effect we want to model doesn’t replace diffuse reflection, but instead complements it.
请注意,如果你在一个红色的台球周围走动,它就会保持红色,但赋予它闪亮外观的亮白点会随着你的走动而移动。这表明我们想要模拟的新效果并不取代漫反射,而是对它的补充。

To understand why this happens, let’s take a closer look at how surfaces reflect light. As we saw in the previous section, when a ray of light hits the surface of a matte object, it’s scattered back to the scene equally in every direction. This happens because the surface of the object is irregular, so at the microscopic level it behaves like a set of tiny surfaces pointing in random directions (Figure 3-8):
为了理解为什么会发生这种情况,让我们仔细看看表面如何反射光线。正如我们在上一节中所看到的,当一束光照射到哑光物体的表面时,它在每个方向上都会平均散射回场景。这是因为物体的表面是不规则的,所以在微观层面上,它的行为就像一组指向随机方向的微小表面(图3-8)。

Figure 3-8: What the rough surface of a matte object might look like through a microscope. The incident rays of light are reflected in random directions.

But what if the surface isn’t that irregular? Let’s go to the other extreme: a perfectly polished mirror. When a ray of light hits a mirror, it’s reflected in a single direction. If we call the direction of the reflected light R, and we keep the convention that L points toward the light source, Figure 3-9 illustrates the situation.
但如果表面不是那么不规则呢?让我们去看看另一个极端:一面完美抛光的镜子。当一束光照射到镜子上时,它被反射到一个方向上。如果我们把反射光的方向称为R⃗ 𝑅 →,并且保持L⃗ 𝐿 →指向光源的惯例,图3-9说明了这种情况。

Figure 3-9: Rays of light reflected by a mirror

Depending on how “polished” the surface is, it behaves more or less like a mirror; this is why it’s called specular reflection, from speculum, the Latin word for mirror.
根据表面的 "抛光 "程度,它的行为或多或少像一面镜子;这就是为什么它被称为镜面反射,来自speculum,拉丁语中的镜子。

For a perfectly polished mirror, the incident ray of light L is reflected in a single direction, R. This is why you see reflected objects very clearly: for every incident ray of light L, there’s a single reflected ray R. But not every object is perfectly polished; while most of the light is reflected in the direction of R, some of it is reflected in directions close to R. The closer to R, the more light is reflected in that direction, as you can see in Figure 3-10. The “shininess” of the object is what determines how rapidly the reflected light decreases as you move away from R.
对于一面完美抛光的镜子,入射光线L ⃗ 𝐿 →被反射到一个方向,即R ⃗ 𝑅 →。这就是为什么你能非常清楚地看到反射的物体:对于每一条入射光线L⃗ 𝐿 →,都有一条反射光线R⃗ 𝑅 →。但并不是每个物体都是完全抛光的;虽然大部分光线在R ⃗ 𝑅 →的方向上被反射,但有些光线在接近R ⃗ 𝑅 →的方向上被反射。越靠近R⃗ 𝑅 →,在该方向上反射的光就越多,正如你在图3-10中看到的那样。物体的 "光泽度 "决定了当你远离R⃗ 𝑅 →时,反射光减少的速度。

Figure 3-10: For surfaces that aren’t perfectly polished, the closer a direction is to \vec{\mathsf{R\}\}, the more rays of light are reflected in that direction.

We want to figure out how much light from L is reflected back in the direction of our point of view. If V is the “view vector” pointing from P to the camera, and α is the angle between R and V, we get Figure 3-11.
我们想知道从L ⃗ 𝐿 →有多少光线被反射回我们的视点方向。如果V ⃗ 𝑉 → 是指从P 𝑃指向摄像机的 "视线矢量",而α 𝛼 是R ⃗ 𝑅 → 和V ⃗ 𝑉 → 之间的角度,我们得到图 3-11。

Figure 3-11: The vectors and angles involved in the specular reflection calculation

For α=0, all the light is reflected in the direction of V. For α=90, no light is reflected. As with diffuse reflection, we need a mathematical expression to determine what happens for intermediate values of α.
当α= 0 ∘ 𝛼 = 0 ∘时,所有的光线都向 V ⃗ 𝑉 → 的方向反射。对于α=90 ∘ 𝛼=90 ∘,没有光线被反射。与漫反射一样,我们需要一个数学表达式来确定在α𝛼的中间值下会发生什么。

Modeling Specular Reflection 镜面反射建模

At the beginning of this chapter, I mentioned that some models aren’t based on physical models. This is one of them. The following model is arbitrary, but it’s used because it’s easy to compute and it looks good.
在这一章的开头,我提到有些模型不是基于物理模型的。这就是其中之一。下面的模型是任意的,但它被使用是因为它很容易计算,而且看起来不错。

Consider cos(α). It has the nice properties that cos(0)=1 and cos(±90)=0, just like we need; and the values become gradually smaller from 0 to 90 in a very pleasant curve (Figure 3-12).
考虑cos(α) 𝑐 𝑜 𝑠 ( 𝛼 ) 。它有一个很好的特性:cos(0)=1 𝑐 𝑜 𝑠 ( 0 ) = 1,cos(±90)=0 𝑐 𝑜 𝑠 ( ± 90 ) = 0,就像我们需要的那样;而且数值从0 0到90 90,在一个非常令人愉快的曲线中逐渐变小(图 3-12)。

Figure 3-12: The graph of cos(\boldsymbol{\alpha}).

This means cos(α) matches all of our requirements for the specular reflection function, so why not use it?
这意味着cos(α) 𝑐 𝑜 𝑠 ( 𝛼 ) 符合我们对镜面反射函数的所有要求,所以为什么不使用它?

There’s one more detail. If we used this formula straight away, every object would be equally shiny. How can we adapt the equation to represent varying degrees of shininess?
还有一个细节。如果我们直接使用这个公式,每个物体都会同样闪亮。我们如何调整这个公式以表示不同程度的光泽?

Remember that shininess is a measure of how quickly the reflection function decreases as α increases. A simple way to obtain different shininess curves is to compute the power of cos(α) to some positive exponent s. Since 0cos(α)1, we are guaranteed that 0cos(α)s1; so cos(α)s is just like cos(α), only “narrower.” Figure 3-13 shows the graph for cos(α)s for different values of s.
记住,光泽度是衡量反射函数随着α𝛼的增加而减少的速度。获得不同光泽度曲线的一个简单方法是计算cos(α) 𝑐 𝑜 𝑠 ( 𝛼 ) 到某个正指数s 𝑠的功率。由于0≤cos(α)≤1 0≤𝑐 𝑜 𝑠 ( 𝛼 ) ≤ 1,我们可以保证0≤cos(α ) s ≤1 0≤𝑐 𝑜 𝑠 ( 𝛼 ) 𝑠 ≤ 1;所以cos(α ) s 𝑐 𝑜 𝑠 ( 𝛼 ) 𝑠 就像cos(α) 𝑐 𝑠 ( 𝛼 ),只是 "更窄"。图3-13是cos(α ) s 𝑐 𝑜 𝑠 ( 𝛼 ) 𝑠在不同s值下的图形。

Figure 3-13: The graph of cos(\boldsymbol{\alpha})s

The bigger the value of s, the “narrower” the function becomes around 0 and the shinier the object looks. s is called the specular exponent and it’s a property of the surface. Since the model is not based on physical reality, the values of s can only be determined by trial and error—essentially, tweaking the values until they look “right.” For a physically based model, you can look into bi-directional reflectance functions (BDRFs).
s𝑠的值越大,函数在0 0附近变得越 "窄",物体看起来越闪亮。由于这个模型不是基于物理现实,s 𝑠的值只能通过试验和错误来确定--基本上,调整这些值直到它们看起来 "正确"。对于一个基于物理的模型,你可以研究双向反射函数(BDRFs)。

Let’s put all of this together. A ray of light hits a surface with specular exponent s at point P, where its normal is N, from direction L. How much light is reflected toward the viewing direction V?
让我们把所有这些放在一起。一束光从L⃗ᵃ→的方向射到一个具有镜面指数s𝑠的表面,其法线是N⃗𝑁→。向观察方向V⃗ 𝑉 →反射的光有多少?

According to our model, this value is cos(α)s, where α is the angle between V and R; R is in turn L reflected with respect to N. So the first step is to compute R from N and L.
根据我们的模型,这个值是cos(α ) s 𝑐 𝑜 𝑠 ( 𝛼 ) 𝑠,其中α 𝛼是V ⃗ 𝑉 → 与R ⃗ 𝑅 → 的角度;R ⃗ 𝑅 → 又是L ⃗ 𝐿 → 相对于 N ⃗ 𝑁 → 的反射。因此,第一步是根据N⃗𝑅→和L⃗𝐿→来计算R⃗𝑁→。

We can decompose L into two vectors, LP and LN, such that L=LN+LP, where LN is parallel to N and LP is perpendicular to N (Figure 3-14).
我们可以将L ⃗ 𝐿 →分解为两个向量,L P → 𝐿 𝑃 →和L N → 𝐿 𝑁 →,这样,L ⃗ = L N → + L P → 𝐿 → = 𝐿 𝑁 → + 𝐿 𝑃 →。其中L N → 𝐿 𝑁 →与N ⃗ 𝑁 →平行,L P → 𝐿 𝑃 →垂直于N ⃗ 𝑁 →(图3-14)。

Figure 3-14: Decomposing \vec{\mathsf{L\}\} into its components \vec{\mathsf{L_P\}\} and \vec{\mathsf{L_N\}\}

LN is the projection of L over N; by the properties of the dot product and the fact that |N|=1, the length of this projection is N,L. We defined LN to be parallel to N, so LN=NN,L.
L N → 𝐿 𝑁 →是L ⃗ 𝐿 →在N ⃗ 𝑁 →上的投影;根据点积的特性和| N ⃗ |=1 | 𝑁 → |=1的事实,这个投影的长度是⟨ N ⃗ ,L ⃗ ⟩ 𝑁 → ,𝐿 → ⟩。我们定义L N → 𝐿 𝑁 →与N ⃗ 𝑁 →平行,所以L N → = N ⃗ ⟨ N ⃗ , L ⃗ ⟩ 𝐿 𝑁 → = 𝑁 → ⟨ 𝑁 → , 𝐿 →⟩。

Since L=LP+LN, we can immediately get LP=LLN=LNN,L.
由于L ⃗ = L P → + L N → 𝐿 → = 𝐿 𝑃 → + 𝐿 𝑁 →,我们可以立即得到L P → = L ⃗ - L N → = L ⃗ - N ⃗ ⟨ N ⃗ ,L ⃗ ⟩ 𝐿 𝑃 → = 𝐿 → - 𝐿 𝑁 → = 𝐿 → - 𝑁→ ⟨𝑁→, 𝐿 → ⟩ 。

Now let’s look at R. Since it’s symmetrical to L with respect to N, its component parallel to N is the same as L’s, and its perpendicular component is the opposite of L’s; that is, R=LNLP. You can see this in Figure 3-15.
现在我们来看看R ⃗ 𝑅 →。由于它与L ⃗ 𝐿 →相对于N ⃗ 𝑁 →对称,它与N ⃗ 𝑁 →平行的部分与L ⃗ 𝐿 →的相同,而其垂直部分与L ⃗ 𝐿 →的相对。也就是说,R ⃗ = L N → - L P → 𝑅 → = 𝐿 𝑁 → - 𝐿 𝑃 →。你可以在图3-15中看到这一点。

Figure 3-15: Computing \vec{\mathsf{L_R\}\}

Substituting with the expressions we found above, we get
用我们上面找到的表达式代入,我们可以得到

R=NN,LL+NN,L
r ⃗ = n ⃗ ⟨ n ⃗ , l ⃗ ⟩- l ⃗ + n ⃗ ⟨ n ⃗ , l ⃗ ⟩ 𝑅 → = 𝑁 → ⟨ 𝑁 → , 𝐿 → ⟩ - 𝐿 → + 𝑁 → ⟨ 𝑁 → , 𝐿 → ⟩

and simplifying a bit 并简化了一下

R=2NN,LL
r ⃗ =2 n ⃗ ⟨ n ⃗ , l ⃗ ⟩- l ⃗ 𝑅 → = 2 𝑁 → ⟨ 𝑁 → , 𝐿 → ⟩ - 𝐿 →

The Specular Reflection Term
镜面反射条款

We’re now ready to write an equation for the specular reflection:
我们现在准备为镜面反射写一个方程式。

R=2NN,LL
r ⃗ =2 n ⃗ ⟨ n ⃗ , l ⃗ ⟩- l ⃗ 𝑅 → = 2 𝑁 → ⟨ 𝑁 → , 𝐿 → ⟩ - 𝐿 →

IS=IL(R,V|R||V|)s
I S = I L ( ⟨ R ⃗ , V ⃗ ⟩ | R ⃗ || V ⃗ | ) 与 𝐼 𝑆 = 𝐿 ( ⟨ 𝑅 → , 𝑉 → | 𝑅 → | 𝑉 → |) 𝑠

As with diffuse lighting, it’s possible that cos(α) is negative, and we should ignore it for the same reason as before. Also, not every object has to be shiny; for matte objects, the specular term shouldn’t be computed at all. We’ll note this in the scene by setting their specular exponent to 1 and handling them accordingly.
与漫反射光照一样,cos(α) 𝑐 𝑜 𝑠 ( 𝛼 ) 有可能是负数,我们应该忽略它,原因与之前一样。另外,并不是每个物体都必须是闪亮的;对于哑光物体,镜面项根本就不应该被计算。我们将在场景中注意到这一点,将它们的镜面指数设置为-1-1,并相应地处理它们。

The Full Illumination Equation
完整的光照方程式

We can add the specular reflection term to the illumination equation we’ve been developing and get a single expression that describes illumination at a point:
我们可以将镜面反射项添加到我们一直在开发的照明方程中,得到一个描述点上照明的单一表达式。

IP=IA+i=1nIi[N,Li|N||Li|+(Ri,V|Ri||V|)s]
I P = I A + ∑ i=1 n I i ⋅ ⎡ ⎣ ⎢ ⟨ N ⃗ , L i → ⟩ | N ⃗ || L i → | + ⎛ ⎝ ⟨ R i → , V ⟩ | R i → || V ⃗ | ⎞ ⎠ s ⎤ ⎦⎥ 𝐼 𝑃 = 𝐼 𝐴 + ∑𝑖 = 1𝑛 𝐼 𝑖⋅ [ ⟨ 𝑁 → 。𝐿 𝑖 → ⟩ | 𝑁 | 𝐿 𝑖 → | + ( ⟨ 𝑅 𝑖 → , 𝑉 → ⟩ | 𝑅 𝑠 ]

where IP is the total illumination at point P, IA is the intensity of the ambient light, N is the normal of the surface at P, V is the vector from P to the camera, s is the specular exponent of the surface, Ii is the intensity of light i, Li is the vector from P to light i, and Ri is the reflection vector at P for light i.
其中,I P 𝐼 𝑃是P𝑃点的总照度,I A 𝐼 𝐴是环境光的强度,N 𝑁是P𝑃点表面的法线,V 𝑉是从P𝑃到摄像机的矢量。s 𝑠是表面的镜面指数,I i 𝐼 𝑖是光i𝑖的强度,L i 𝐿 𝑖是从P到光i𝑖的矢量,R i 𝑅 𝑖是光i𝑖在P𝑃的反射向量。

Rendering with Specular Reflections
用镜面反射进行渲染

Let’s add specular reflections to the scene we’ve been working with so far. First, some changes to the scene itself:
让我们把镜面反射添加到我们到目前为止一直在使用的场景中。首先,对场景本身做一些改变。

sphere {
    center = (0, -1, 3)
    radius = 1
    color = (255, 0, 0)  # Red
    specular = 500  # Shiny
}
sphere {
    center = (2, 0, 4)
    radius = 1
    color = (0, 0, 255)  # Blue
    specular = 500  # Shiny
}
sphere {
    center = (-2, 0, 4)
    radius = 1
    color = (0, 255, 0)  # Green
    specular = 10  # Somewhat shiny
}
sphere {
    center = (0, -5001, 0)
    radius = 5000
    color = (255, 255, 0)  # Yellow
    specular = 1000  # Very shiny
}

This is the same scene as before, with the addition of specular exponents to the sphere definitions.
这是与之前相同的场景,在球体定义中加入了镜面指数。

At the code level, we need to change ComputeLighting to compute the specular term when necessary, and add it to the overall light. Note that the function now needs V and s, as you can see in Listing 3-2.
在代码层面上,我们需要改变 ComputeLighting ,以便在必要时计算镜面项,并将其添加到整个光线中。注意这个函数现在需要V ⃗ 𝑉 → 和s 𝑠,你可以在清单3-2中看到。

ComputeLighting(P, N, V, s) {
    i = 0.0
    for light in scene.Lights {
        if light.type == ambient {
            i += light.intensity
        } else {
            if light.type == point {
                L = light.position - P
            } else {
                L = light.direction
            }

            // Diffuse
            n_dot_l = dot(N, L)
            if n_dot_l > 0 {
                i += light.intensity * n_dot_l/(length(N) * length(L))
            }

            // Specular
         ❶ if s != -1 {
                R = 2 * N * dot(N, L) - L
                r_dot_v = dot(R, V)
             ❷ if r_dot_v > 0 {
                    i += light.intensity * pow(r_dot_v/(length(R) * length(V)), s)
                }
            }
        }
    }
    return i
}
Listing 3-2: ComputeLighting that supports both diffuse and specular reflections
清单3-2。 同时支持漫反射和镜面反射的 ComputeLighting

Most of the code remains unchanged, but we add a fragment to handle specular reflections. We make sure it applies only to shiny objects ❶ and also make sure we don’t add negative light intensity ❷, as we did for diffuse reflection.
大部分的代码保持不变,但我们增加一个片段来处理镜面反射。我们确保它只适用于闪亮的物体 ❶ ,也确保我们不会像处理漫反射那样,增加负的光强度 ❷ 。

Finally, we need to modify TraceRay to pass the new parameters to Compute Lighting. s is straightforward: it comes directly from the scene definition. But where does V come from?
最后,我们需要修改 TraceRay ,将新的参数传递给 Compute Lighting 。S 𝑠很直接:它直接来自场景定义。但V ⃗ 𝑉 → 从哪里来?

V is a vector that points from the object to the camera. Fortunately, we already have a vector that points from the camera to the object at TraceRay—that’s D, the direction of the ray we’re tracing! So V is simply D.
V ⃗ 𝑉 → 是一个从物体指向摄像机的矢量。幸运的是,我们已经有了一个从相机指向物体的 TraceRay 的向量--那就是D ⃗ 𝐷 →,也就是我们要追踪的射线的方向所以V ⃗ 𝑉 →就是 - D ⃗ - 𝐷 →。

Listing 3-3 gives the new TraceRay with specular reflection.
清单3-3给出了带有镜面反射的新 TraceRay

TraceRay(O, D, t_min, t_max) {
    closest_t = inf
    closest_sphere = NULL
    for sphere in scene.Spheres {
        t1, t2 = IntersectRaySphere(O, D, sphere)
        if t1 in [t_min, t_max] and t1 < closest_t {
            closest_t = t1
            closest_sphere = sphere
        }
        if t2 in [t_min, t_max] and t2 < closest_t {
            closest_t = t2
            closest_sphere = sphere
        }
    }
    if closest_sphere == NULL {
        return BACKGROUND_COLOR
    }

    P = O + closest_t * D  // Compute intersection
    N = P - closest_sphere.center  // Compute sphere normal at intersection
    N = N / length(N)
 ❶ return closest_sphere.color * ComputeLighting(P, N, -D, closest_sphere.specular)
}
Listing 3-3: TraceRay with specular reflection
清单3-3:带有镜面反射的 TraceRay

The color calculation ❶ is slightly more involved than it looks. Remember that colors must be multiplied channel-wise and the results must be clamped to the range of the channel (in our case, [0–255]). Although in the example scene the light intensities add up to 1.0, now that we’re adding the contributions of specular reflections, the values could go beyond that range.
颜色计算❶比它看起来要稍微复杂一些。请记住,颜色必须按通道相乘,并且结果必须被钳制在通道的范围内(在我们的例子中,[0-255])。尽管在示例场景中,光线强度加起来是1.0,但现在我们要加上镜面反射的贡献,数值可能超出这个范围。

You can see the reward for all this vector juggling in Figure 3-16.
你可以在图3-16中看到所有这些矢量杂耍的回报。

Figure 3-16: The scene rendered with ambient, diffuse, and specular reflection. Not only do we get a sense of depth and volume, but each surface also has a slightly different appearance.

Source code and live demo >>
源代码和现场演示 >>

Note that in Figure 3-16, the red sphere with a specular exponent of 500 has a more concentrated bright spot than the green sphere with a specular exponent of 10, exactly as expected. The blue sphere also has a specular exponent of 500 but no visible bright spot. This is only a consequence of how the image is cropped and how the lights are placed in the scene; indeed, the left half of the red sphere also doesn’t exhibit any specular reflection.
请注意,在图3-16中,镜面指数为500的红色球体比镜面指数为10的绿色球体有一个更集中的亮点,与预期完全一致。蓝色球体的镜面指数也是500,但没有明显的亮点。这只是图像的裁剪方式和灯光在场景中的放置方式的结果;事实上,红色球体的左半部分也没有表现出任何镜面反射。

Summary

In this chapter, we’ve taken the very simple raytracer developed in the previous chapter and given it the ability to model lights and the way they interact with the objects in the scene.
在这一章中,我们采用了上一章中开发的非常简单的光线跟踪器,并赋予它为灯光建模的能力,以及它们与场景中的物体交互的方式。

We split lights into three types: point, directional, and ambient. We explored how each of them can represent a different type of light that you can find in real life, and how to describe them in our scene definition.
我们把灯光分成三种类型:点式、定向式和环境式。我们探讨了它们中的每一种如何代表你在现实生活中可以找到的不同类型的光,以及如何在我们的场景定义中描述它们。

We then turned our attention to the surface of the objects in the scene, splitting them into two types: matte and shiny. We discussed how rays of light interact with them and developed two models—diffuse and specular reflection—to compute how much light they reflect toward the camera.
然后我们把注意力转移到场景中物体的表面,把它们分成两种类型:哑光和亮光。我们讨论了光线如何与它们相互作用,并建立了两个模型--漫反射和镜面反射--来计算它们向摄像机反射多少光线。

The end result is a much more realistic rendering of the scene: instead of seeing just the outlines of the objects, we now get a real sense of depth and volume and a feel for the materials the objects are made of.
最终的结果是对场景进行了更真实的渲染:我们现在看到的不再是物体的轮廓,而是真正的深度和体积感,以及对物体的材质的感觉。

However, we are missing a fundamental aspect of lights: shadows. This is the focus of the next chapter.
然而,我们缺少灯光的一个基本方面:阴影。这是下一章的重点。