Introductory Concepts 介绍性的概念

A raytracer and a rasterizer take very different approaches to rendering a 3D scene onto a 2D screen. However, there are a few fundamental concepts that are common to both approaches.
光线追踪器和光栅器采取了非常不同的方法来将3D场景渲染到2D屏幕上。然而,两种方法都有一些共同的基本概念。

In this chapter, we’ll explore the canvas, the abstract surface on which we’ll render our images; the coordinate system we’ll use to refer to pixels on the canvas; how to represent and manipulate colors; and how to describe a 3D scene so our renderers can work with it.
在本章中,我们将探讨画布,即我们将渲染图像的抽象表面;我们将用来指代画布上的像素的坐标系统;如何表示和处理颜色;以及如何描述一个三维场景,以便我们的渲染器能够处理它。

The Canvas 帆布

Throughout this book, we’ll be drawing things on a canvas: a rectangular array of pixels that can be individually colored. Whether this canvas is shown on a screen or printed on paper is irrelevant to our purposes. Our goal is to represent a 3D scene on a 2D canvas, so we’ll focus on rendering to this abstract, rectangular array of pixels.
在本书中,我们将在画布上画东西:一个矩形的像素阵列,可以单独着色。无论这个画布是显示在屏幕上还是打印在纸上,都与我们的目的无关。我们的目标是在二维画布上表现一个三维场景,所以我们将专注于对这个抽象的矩形像素阵列进行渲染。

We’ll build everything in this book out of a single, very simple function, which assigns a color to a pixel on the canvas:
我们将用一个非常简单的函数来构建本书中的所有内容,这个函数为画布上的一个像素分配颜色。

canvas.PutPixel(x, y, color)

This method has three arguments: an x coordinate, a y coordinate, and a color. Let’s focus on the coordinates for now.
这个方法有三个参数:一个 x 坐标,一个 y 坐标,以及一个颜色。现在让我们把重点放在坐标上。

Coordinate Systems 坐标系统

The canvas has a width and a height, measured in pixels, which we’ll call Cw and Ch. We need a coordinate system to refer to its pixels. For most computer screens, the origin is at the top left; x increases toward the right of the screen, and y increases toward the bottom, as in Figure 1-1.
画布有一个宽度和高度,以像素为单位,我们称之为C w 𝐶 𝑤和C h 𝐶 ℎ。我们需要一个坐标系来指代其像素。对于大多数计算机屏幕来说,原点在左上方;x𝑥向屏幕右侧增加,y𝑦向底部增加,如图1-1。

Figure 1-1: The coordinate system used by most computer screens

This coordinate system is very natural for a computer because of the way video memory is organized, but it’s not the most natural for humans to work with. Instead, 3D graphics programmers tend to use the coordinate system typically used to draw graphs on paper: the origin is at the center, x increases toward the right and decreases toward the left, while y increases toward the top and decreases toward the bottom, as in Figure 1-2.
由于视频存储器的组织方式,这种坐标系对计算机来说是非常自然的,但对人类来说,它并不是最自然的工作方式。相反,3D图形程序员倾向于使用通常用于在纸上画图的坐标系统:原点在中心,x𝑥向右增加,向左减少,而y𝑦向顶部增加,向底部减少,如图1-2所示。

Figure 1-2: The coordinate system we’ll use for our canvas

Using this coordinate system, the range of the x coordinate is [Cw2,Cw2) and the range of the y coordinate is [Ch2,Ch2). Let’s assume that using the PutPixel function with coordinates outside these ranges does nothing.
使用这个坐标系,x𝑥坐标的范围是[ - C w 2 , C w 2 ) [ - 𝐶 𝑤 2 , 𝐶 𝑤 2 ) ,y 𝑦坐标的范围是[ - C h 2 , C h 2 ) [ - 𝐶 ℎ 2 , 𝐶 ℎ 2 ) 。我们假设在这些范围之外的坐标上使用 PutPixel 函数没有任何作用。

In our examples, the canvas will be drawn on the screen, so we’ll need to convert from one coordinate system to the other. To do this, we need to change the center of the coordinate system and reverse the direction of the Y axis. The resulting conversion equations are:
在我们的例子中,画布将被画在屏幕上,所以我们需要从一个坐标系转换到另一个坐标系。要做到这一点,我们需要改变坐标系的中心,并颠倒Y𝑌轴的方向。由此产生的转换方程是。

Sx=Cw2+Cx

Sy=Ch2Cy
S y = C h 2 - C y 𝑆 𝑦 = 𝐶 ℎ 2 - 𝐶 𝑦

We will assume PutPixel does this conversion automatically; from this point on, we can think of the canvas as having its coordinate origin at the center, with x increasing to the right and y increasing to the top of the screen.
我们将假设 PutPixel 自动进行这种转换;从这一点上看,我们可以认为画布的坐标原点在中心,x𝑥向右增加,y𝑦向屏幕的顶部增加。

Let’s take a look at the remaining argument of PutPixel: the color.
让我们来看看 PutPixel 的其余参数:颜色。

Color Models 彩色模型

The theory of how color works is fascinating, but it’s outside the scope of this book. The following is a simplified version of the aspects relevant to us.
颜色如何工作的理论很吸引人,但这不在本书的范围之内。以下是与我们有关的方面的简化版本。

When light hits our eyes, it stimulates the light-sensitive cells at their back. These generate signals on our brains, that depend on the wavelength of the incoming light. We call the subjective experience of these brain signals colors.
当光线照射到我们的眼睛时,它刺激了眼睛后面的感光细胞。这些细胞在我们的大脑中产生信号,这些信号取决于入射光线的波长。我们称这些大脑信号的主观体验为颜色。

We can only see light in a certain range of wavelengths, called the visible range. Wavelength and frequency are inversely related: the more frequently the wave hits, the smaller the distance between the peaks of that wave, and the more energy is carried by the wave. This is why infrared (wavelengths longer than 740 nm, corresponding to frequencies lower than 405 terahertz [THz]) is harmless, but ultraviolet (wavelengths shorter than 380 nm, corresponding to frequencies higher than 790 THz) can burn your skin.
我们只能看到一定波长范围内的光,称为可见范围。波长和频率是成反比的:波打得越频繁,该波峰之间的距离就越小,波所携带的能量也就越多。这就是为什么红外线(波长长于740纳米,对应的频率低于405太赫兹[THz])是无害的,但紫外线(波长短于380纳米,对应的频率高于790太赫兹)会灼伤皮肤。

Every color imaginable can be described as a combination of different wavelengths. For example, “White” is the sum of all wavelengths, while “black” is the absence of any light. It would be impractical to describe colors by listing all the wavelengths they’re made of; fortunately, it’s possible to describe almost all colors as a linear combination of just three colors, which we call primary colors.
可以想象的每一种颜色都可以被描述为不同波长的组合。例如,"白色 "是所有波长的总和,而 "黑色 "是没有任何光线。通过列出所有的波长来描述颜色是不切实际的;幸运的是,我们可以把几乎所有的颜色描述成三种颜色的线性组合,我们称之为原色。

Subtractive Color Model 减法颜色模型

The subtractive color model is a fancy name for that thing you did with crayons as a toddler. You take a white piece of paper and red, blue, and yellow crayons. You draw a yellow circle, then a blue circle that overlaps it, and you get green! Yellow and red—orange! Red and blue—purple! Mix the three together—something darkish! Wasn’t kindergarten amazing? Figure 1-3 shows the primary colors of the subtractive model, and the colors that result from mixing them.
减法色彩模型是你在学步时用蜡笔做的那件事的一个华丽的名字。你拿一张白纸和红、蓝、黄蜡笔。你画一个黄色的圆圈,然后再画一个蓝色的圆圈与之重叠,你就得到了绿色!这就是减色法。黄色和红橙色!红色和蓝色--紫色!将三者混合在一起--就会出现深色的东西!幼儿园不是很神奇吗?图1-3显示了减法模型的原色,以及将它们混合后的颜色。

Figure 1-3: Subtractive primary colors and their combinations

Objects are of different colors because they absorb and reflect light in different ways. Let’s start with white light, like sunlight (sunlight isn’t quite white, but it’s close enough for our purposes). White light contains light of every wavelength. When it hits an object, the object’s surface absorbs some of the wavelengths and reflects others, depending on the material. Some of the reflected light then hits our eyes, and our brains convert that to color. What color? The sum of the wavelengths that were reflected by the surface.
物体之所以有不同的颜色,是因为它们以不同的方式吸收和反射光线。让我们从白光开始,比如阳光(阳光并不完全是白色的,但对我们的目的来说已经很接近了)。白光包含各种波长的光。当它照射到一个物体上时,该物体的表面会吸收一些波长的光,并反射其他波长的光,这取决于材料的不同。一些反射的光然后进入我们的眼睛,我们的大脑将其转换为颜色。什么颜色?就是被物体表面反射的波长的总和。

So what’s going on with the crayons? You start with white light reflecting off the paper. Since it’s white paper, it reflects most of the light it receives. When you draw with a “yellow” crayon, you’re adding a layer of a material that absorbs some wavelengths but lets others pass through it. They’re reflected by the paper, pass through the yellow layer again, hit your eyes, and your brain interprets that particular combination of wavelengths as “yellow.” What the yellow layer does is subtract a bunch of wavelengths from the original white light.
那么,蜡笔的情况是怎样的呢?你开始用白光在纸上反射。由于它是白纸,它反射了它所接收到的大部分光线。当你用 "黄色 "蜡笔作画时,你添加了一层材料,吸收了一些波长,但让其他波长通过它。它们被纸反射,再次通过黄色层,击中你的眼睛,而你的大脑将这种特定的波长组合解释为 "黄色"。黄色层所做的是在原始白光中减去一堆波长。

You can think of each colored circle as a filter: when you draw a blue circle overlapping the yellow one, you’re filtering out even more wavelengths from the original light, so what hits your eyes is whatever wavelengths weren’t filtered by either the blue or the yellow circles, which your brain sees as “green.”
你可以把每个彩色圆圈看作是一个过滤器:当你在黄色圆圈上画一个蓝色圆圈时,你从原来的光线中过滤掉了更多的波长,所以进入你眼睛的是没有被蓝色或黄色圆圈过滤掉的波长,你的大脑把这些波长看作是 "绿色"。

In summary, we start with all wavelengths and subtract some amount of the primary colors to create any other color. This color model gets its name from the fact that we’re creating colors by subtracting wavelengths.
总之,我们从所有的波长开始,减去一定量的原色来创造任何其他颜色。这个颜色模型的名字来自于我们通过减去波长来创造颜色这一事实。

This model isn’t quite right, though. The actual primary colors in the subtractive model aren’t the blue, red, and yellow taught to toddlers and art students, but cyan, magenta, and yellow. Furthermore, mixing the three primary colors produces a somewhat darkish color that isn’t quite black, so pure black is added as a fourth “primary.” Because B is used to represent blue, black is denoted by K, and so we arrive at the CMYK color model (Figure 1-4).
不过,这种模式并不完全正确。在减法模型中,实际的原色并不是幼儿和艺术学生所学的蓝色、红色和黄色,而是青色、洋红色和黄色。此外,将这三种原色混合在一起会产生一种有点偏暗的颜色,但又不完全是黑色,所以纯黑被添加为第四种 "原色"。因为B是用来代表蓝色的,所以黑色用K来表示,这样我们就得到了CMYK颜色模型(图1-4)。

You can see evidence of this color model directly on the cartridges of color printers, or sometimes in the shapes of cheaply printed flyers where the different colors are slightly offset from one another.
你可以直接在彩色打印机的墨盒上看到这种颜色模式的证据,或者有时在廉价印刷的传单的形状中看到不同的颜色相互之间略有偏移。

Figure 1-4: The four subtractive primary colors used by printers

Additive Color Model 添加性色彩模型

The subtractive color model is only half the story. If you’ve ever looked at a screen up close or with a magnifying glass (or, let’s be honest, accidentally sneezed on it), you’ve probably seen tiny colored dots: these are red, green, and blue.
减法色彩模型只是故事的一半。如果你曾经近距离或用放大镜观察过屏幕(或者,说实话,不小心在上面打了个喷嚏),你可能看到过一些微小的彩色点:这些是红、绿、蓝。

Computer screens are the opposite of paper. Paper doesn’t emit light; it merely reflects part of the light that hits it. Screens, on the other hand, are black, but they do emit light on their own. With paper, we start with white light and subtract the wavelengths we don’t want; with a screen, we start with no light and add the wavelengths we want.
计算机屏幕与纸张正好相反。纸张不发光;它只是反射部分照射到它的光线。另一方面,屏幕是黑色的,但它们自己确实在发光。对于纸张,我们从白光开始,然后减去我们不想要的波长;对于屏幕,我们从没有光开始,然后加上我们想要的波长。

Different primary colors are necessary for this. Most colors can be created by adding different amounts of red, green, and blue to a black surface; this is the RGB color model, an additive color model, shown in Figure 1-5.
为此,不同的原色是必要的。大多数颜色可以通过向黑色表面添加不同数量的红、绿、蓝来创造;这就是RGB颜色模型,一种加色模型,如图1-5所示。

The combination of additive primary colors is lighter than its components, whereas the combination of subtractive primary colors is darker; all the additive primaries add up to white, while all the subtractive primaries add up to black.
加法原色的组合比其组成部分要浅,而减法原色的组合则要深;所有加法原色加起来是白色,而所有减法原色加起来是黑色。

Figure 1-5: The additive primary colors and some of their combinations

Forget the Details 忘记细节

Now that you know all this, you can selectively forget most of the details and focus on what’s important for our work.
现在你知道了这一切,你可以有选择地忘记大部分细节,专注于对我们的工作来说重要的东西。

Most colors can be represented in either RGB or CMYK (or in any of the many other color models), and it’s possible to convert from one color space to another. Since we’re focusing on rendering things on a screen, we use the RGB color model for the rest of this book.
大多数颜色都可以用RGB或CMYK(或其他许多颜色模型中的任何一种)来表示,而且可以从一种颜色空间转换到另一种。由于我们的重点是在屏幕上渲染东西,所以在本书的其余部分我们使用RGB颜色模型。

As described above, objects absorb part of the light reaching them and reflect the rest. Which wavelengths are absorbed and which are reflected is what we perceive as the “color” of the surface. From now on, we’ll simply treat the color as a property of a surface and forget about light wavelengths.
如上所述,物体吸收到达它们的部分光线,并反射其余部分。哪些波长被吸收,哪些波长被反射,就是我们所感知的表面的 "颜色"。从现在开始,我们将简单地把颜色当作表面的一个属性,而忘记光的波长。

Color Depth and Representation
颜色的深度和表现

Monitors create colors by mixing different amounts of red, green, and blue. They do this by lighting the tiny colored dots on their surface at different intensities by supplying different voltages to them.
显示器通过混合不同数量的红色、绿色和蓝色来创造颜色。它们是通过向其表面的微小彩色点提供不同的电压,以不同的强度点亮这些小点来实现的。

How many different intensities can we get? Although voltage is continuous, we’ll be manipulating colors with a computer, which uses discrete values (that is, a limited number of them). The more shades of red, green, and blue we can represent, the more colors we’ll be able to produce.
我们可以得到多少种不同的强度?虽然电压是连续的,但我们将用计算机来操作颜色,而计算机使用的是离散值(也就是有限的数量)。我们能表示的红、绿、蓝的色调越多,我们能产生的颜色就越多。

Most images you see these days use 8 bits per primary color, which we call a color channel in this context. Using 8 bits per channel gives us 24 bits per pixel, for a total of 224 different colors (approximately 16.7 million). This format, known as R8G8B8 or simply 888, is the one we’ll use throughout this book. We say this format has a color depth of 24 bits.
你现在看到的大多数图像都使用每一种原色的8比特,在这里我们称之为颜色通道。每个通道使用8比特,每个像素就有24比特,总共有2 24 2 24种不同的颜色(约1670万)。这种格式,被称为R8G8B8或简单的888,是我们在本书中使用的格式。我们说这种格式的颜色深度为24比特。

This is by no means the only possible format. Not so long ago, in order to save memory, 15- and 16-bit formats were popular, assigning 5 bits per channel in the 15-bit case, and 5 bits for red, 6 for green, and 5 for blue in the 16-bit case (known as the R5G6B5 or 565 format). Green gets the extra bit because our eyes are more sensitive to changes in green than to changes in red or blue.
这决不是唯一可能的格式。不久前,为了节省内存,15位和16位的格式很流行,在15位的情况下,每个通道分配5位,在16位的情况下,红色5位,绿色6位,蓝色5位(被称为R5G6B5或565格式)。绿色得到额外的位,因为我们的眼睛对绿色的变化比对红色或蓝色的变化更敏感。

With 16 bits, we get 216 colors (approximately 65,000). This means you get one color for every 256 colors in 24-bit mode. Although 65,000 colors is plenty, for images where colors change very gradually you would be able to see very subtle “steps” that just aren’t visible with 16.7 million colors, where there are enough bits to represent the colors in between. For some specialized applications, such as color grading for movies, it’s a good idea to represent even more color detail, using even more bits per channel.
通过16位,我们可以得到2 16 2 16种颜色(大约65 000种)。这意味着在24位模式下,每256种颜色就能得到一种颜色。尽管65,000种颜色已经够多了,但对于颜色变化非常渐进的图像,你可以看到非常微妙的 "阶梯",而1670万种颜色是看不到的,因为有足够的比特来表示中间的颜色。对于一些专门的应用,如电影的调色,用更多的比特/通道来表示更多的颜色细节是一个好主意。

We’ll use 3 bytes to represent a color, each holding the value of an 8-bit color channel, from 0 to 255. We’ll express the colors as (R,G,B)—for example, (255,0,0) represents pure red; (255,255,255) represents white; and (255,0,128) represents a reddish purple.
我们将用3个字节来表示一种颜色,每个字节保存一个8位颜色通道的值,从0到255。我们将用(R,G,B)( 𝑅 , 𝐺 , 𝐵 )来表示颜色--例如,(255,0,0) ( 255 , 0 , 0 ) 表示纯红色;(255,255,255) ( 255 , 255 , 255 ) 表示白色;而(255,0,128) ( 255 , 0 , 128 ) 表示红紫色。

Color Manipulation 颜色操纵

We’ll use a handful of operations to manipulate colors. If you know some linear algebra, you can think of colors as vectors in 3D color space. If not, don’t worry, we’ll go through the basic operations we’ll be using now.
我们将使用少量的操作来处理颜色。如果你知道一些线性代数,你可以把颜色看作是三维颜色空间的向量。如果不懂,也不用担心,我们会把现在要用的基本操作过一遍。

We can modify the intensity of a color by multiplying each of its color channels by a constant:
我们可以通过将一个颜色的每个通道乘以一个常数来修改一个颜色的强度。

k(R,G,B)=(kR,kG,kB)
k(R,G,B)=(kR,kG,kB) 𝑘 ( 𝑅 , 𝐺 , 𝐵 ) = ( 𝑘 𝑅 , 𝐺 𝐵 )

For example, (32,0,128) is twice as bright as (16,0,64).
例如,(32,0,128)( 32 , 0 , 128)的亮度是(16,0,64)( 16 , 0 , 64)的两倍。

We can add two colors together by adding their color channels separately:
我们可以通过分别添加它们的颜色通道将两种颜色加在一起。

(R1,G1,B1)+(R2,G2,B2)=(R1+R2,G1+G2,B1+B2)
( r 1 , g 1 , b 1 )+( r 2 , g 2 , b 2 )=( r 1 + r 2 , g 1 + g 2 , b 1 + b 2 ) ( 𝑅 1 , 𝐺 1 , 𝐵 1 ) +( 𝑅 2 , 𝐺 2 , 𝐵 2 ) =( 𝑅 1 + 𝐺 2 , 𝐵 1 + 𝐵 2 )

For example, if we want to combine red (255,0,0) and green (0,255,0), we add them channel-wise and get (255,255,0), which is yellow.
例如,如果我们想把红色(255,0,0)( 255 , 0 , 0 )和绿色(0,255,0)( 0 , 255 , 0 )结合起来,我们把它们按通道相加,得到(255,255,0)( 255 , 255 , 0 ),这就是黄色。

These operations can yield invalid values; for example, doubling the intensity of (192,64,32) produces an R value outside our color range. We’ll treat any value over 255 as 255, and any value below 0 as 0; we call this clamping the value to the [0–255] range. This is more or less equivalent to what happens when you take an under- or over-exposed photograph in real life: you get either completely black or completely white areas.
这些操作可能会产生无效的值;例如,将(192,64,32)( 192 , 64 , 32)的强度加倍,会产生一个超出我们颜色范围的R 𝑅值。我们将把任何超过255的值视为255,而把任何低于0的值视为0;我们把这称为将数值夹在[0-255]范围内。这或多或少相当于你在现实生活中拍摄曝光不足或曝光过度的照片时发生的情况:你会得到完全黑色或完全白色的区域。

That about sums it up for our primer on colors and PutPixel. Before we move on to the next chapter, let’s spend a little time exploring how to represent the 3D objects we’ll be rendering.
这就是我们关于颜色和 PutPixel 的入门课程的总结。在我们进入下一章之前,让我们花一点时间来探索如何表示我们将要渲染的三维物体。

The Scene 场景

So far, we have introduced the canvas, the abstract surface on which we can color pixels. Now we turn our attention to the objects we’re interested in representing by introducing another abstraction: the scene.
到目前为止,我们已经介绍了画布,这个抽象的表面,我们可以在上面给像素着色。现在我们把注意力转移到我们感兴趣的物体上,引入另一个抽象概念:场景。

The scene is the set of objects you may be interested in rendering. It could represent anything, from a single sphere floating in the empty infinity of space (we’ll start there) to an incredibly detailed model of the inside of a grumpy ogre’s nose.
场景是你可能有兴趣渲染的对象的集合。它可以代表任何东西,从漂浮在空旷的无限空间中的一个球体(我们将从这里开始)到一个暴躁的食人魔的鼻子内部的令人难以置信的详细模型。

We need a coordinate system to talk about objects within the scene. We can’t use the same coordinate system as the canvas, for two reasons. First, the canvas is 2D, whereas the scene is 3D. Second, the canvas and the scene use different units: we use pixels for the canvas and real-world units (such as the imperial or metric systems) for the scene.
我们需要一个坐标系来谈论场景中的物体。我们不能使用与画布相同的坐标系,原因有二。首先,画布是2D的,而场景是3D的。第二,画布和场景使用不同的单位:我们对画布使用像素,对场景使用现实世界的单位(比如英制或公制)。

The choice of axes is arbitrary, so we’ll pick something useful for our purposes. We’ll say that Y is up and X and Z are horizontal, and all three axes are perpendicular to each other. Think of the plane XZ as the “floor,” while XY and YZ are vertical “walls” in a square room. This is consistent with the coordinate system we chose for the canvas, where Y is up and X is horizontal. Figure 1-6 shows what this looks like.
轴的选择是任意的,所以我们将选择对我们的目的有用的东西。我们说Y𝑌是向上的,X𝑋和Z𝑍是水平的,所有三个轴都是相互垂直的。把平面XZ𝑋𝑍看作是 "地板",而XY𝑋𝑌和YZ𝑌𝑍是一个方形房间的垂直 "墙壁"。这与我们为画布选择的坐标系统一致,Y𝑌是向上的,X𝑋是水平的。图1-6显示了这种情况的样子。

Figure 1-6: The coordinate system we’ll use for our scenes

The choice of scene units is somewhat arbitrary; it depends on what your scene represents. A measurement of “1” could mean 1 inch if you’re modeling a teacup, or it could mean 1 astronomical unit if you’re modeling the Solar System. As long as we use our chosen units consistently, it doesn’t matter what they are, so we can safely ignore them from now on.
场景单位的选择是有些随意的;它取决于你的场景代表什么。如果你在为一个茶杯建模,"1 "的测量值可能意味着1英寸,如果你在为太阳系建模,它可能意味着1个天文单位。只要我们一致地使用我们选择的单位,它们是什么并不重要,所以从现在开始我们可以安全地忽略它们。

Summary

In this chapter, we’ve introduced the canvas, an abstraction that represents a rectangular surface we can draw on, plus the one method we’ll build everything else on: PutPixel. We’ve also chosen a coordinate system to refer to the pixels on the canvas and described a way to represent the color of these pixels. Lastly, we introduced the concept of a scene and chose a coordinate system to use in the scene.
在这一章中,我们介绍了画布,它是一个抽象概念,代表了我们可以在上面作画的矩形表面,另外还有一个方法,我们将在上面建立其他的东西。 PutPixel .我们还选择了一个坐标系来指代画布上的像素,并描述了一种表示这些像素颜色的方法。最后,我们介绍了一个场景的概念,并选择了一个坐标系在场景中使用。

Having laid these foundations, it’s time to start building a raytracer and a rasterizer on top of them.
在奠定了这些基础之后,现在是时候开始在这些基础上建立一个光线追踪器和光栅器了。