基本思路:

对每个像素

  • 生成观测射线
  • 求出观测射线碰到的最近的物体,得到碰撞点的相关信息
  • 利用已知的各种信息来决定该点的颜色

观测射线的建立

首先建立观察坐标系,在该坐标系下描述射线.对于透视成像, 可选观测点为原点, 指定观测方向和up方向,另一个轴可根据左/右手原则确定.选择距观测点一定距离的平面作为成像面, 成像面上划出一块矩形区域作为成像区域, 对区域中每个像素点来说,从观测点到自己的射线即为观测射线.

射线求交

要解决射线求交的问题,先来考虑几种最基础的情形:

  • 射线和球面求交, 联立射线和球面方程求解二次方程即可.

  • 射线和三角形求交.

    三角形由三顶点ABC给出, 则三角形平面上任意一点可表为 xA+yB+zC的形式. 其中x+y+z=1

    联立射线方程求解即可,若射线与平面相交且交点在内部,则x,y,z均在0,1范围内.

  • 射线和平面多边形求交.

    先求出射线和平面的交点.再判断交点是否在多边形内部.

    判断内部与否, 可以将交点和多边形顶点都投影至任意一个垂直坐标轴的平面上来进行简化,然后利用如下事实:

    从交点任意做一条射线,当且仅当它和多边形边界交点个数为奇数,该点落在多边形内部.

    为了避免多边形在投影面上退化成一条线段, 可用如下方式选取投影面:

    考虑多边形平面的法线N, 取三分量Nx,Ny,Nz中绝对值最大的那个, 取和该分量所在轴垂直的坐标平面.即,假设x分量绝对值最大,则取与x轴垂直的坐标平面来当投影面.

光照模型

光照模型即如何利用已知的各种信息来确定颜色.

首先考虑如何表示光的颜色和物体的颜色.

假设任意光可由红绿蓝三种单色光按一定比例混合得到,则可用三维向量 L=(r,g,b) 来表示.分量大小代表对应单色光的强度.

物体的颜色和照射它的光有关,(如白纸在红光照射下是红色),脱离光照谈论物体的颜色,指的应该是物体对三种颜色的光的反射能力.例如用(1,0,0)表示物体为红色,则可以理解为该物体能反射全部的红光,吸收全部的绿光和蓝光.因此物体的颜色属性也可以用三维向量表示 K=(r,g,b)其中r,g,b均在范围(0,1)内,表示该物体对三种单色光的反射能力

于是我们有了一个最原始的模型.

光的颜色点积物体的颜色属性 即得到我们看到的颜色

这个模型有明显的不足, 实际上我们注意到光线和它所照射的表面所成的角度会影响表面的明暗.光垂直照射表面时表面显得最亮,光平行于表面时则最暗.我们把光看作是一个向量的话, 可以将该向量分别沿着垂直和平行于表面的方向进行分解.假设只有垂直方向上的分量能被表面接收到,可以得到

颜色 = 物体表面颜色 点积 光的颜色 乘以系数 max(0, n·i) (Lambert模型)

其中n表示平面法向,i表示照射点到光源方向,两者均为单位向量

Lambert模型下,物体的颜色和观察的角度没有关系, 因为该模型实际上假定了光经过照射点反射以后,将在各个方向产生彼此一致的光.即发生了漫反射.

我们进一步考虑, 假设光照射到一点后, 有一部分是沿各个方向均匀反射出去,还有另一部分是大致沿着镜面反射的方向进行反射, 而且越接近镜面反射方向,反射的光就越亮.那么观察方向和镜面反射方向越接近的点应该表现出更亮的颜色.于是我们得到了一个和观察角度有关的着色模型.

具体来说, 高光 = 物体高光颜色 * 入射光颜色 * 观察方向和反射方向的一致程度

为了计算简便,我们可以考虑观察方向和光源方向的中间方向v+i和平面法向n的接近程度, 对前者取单位向量然后做点积即可.即

接近系数 = (v+i).normalize · n

为了能控制高光部分在物体上的紧凑程度, 可以对接近系数取一个常数指数P

于是现在着色模型被修正为

颜色= 漫反射部分 + 高光部分

其中

  • 漫反射 = 物体漫反射颜色 * 入射光 * 法线和光源方向的点积
  • 高光 = 物体高光颜色 * 入射光 * 视线和光源的中间方向与法线的点积 取P次方

该模型目前有一个特点是,不被光直接照射到的地方将是完全黑色.这也不符合实际.光经过环境中各种复杂表面反复反射,能到达很多不能被直接照射的表面,这种现象我们用环境光来模拟.假设环境中任意方向都存在一个独立于入射光的常量光, 那么它也对物体的颜色产生贡献

  • 环境光 = 物体环境光颜色 * 环境光

把三个部分的结果相加, 我们得到了 Blinn-Phong模型

如果场景中存在多个点光源,那么对于每一个光源,把各种产生的漫反射和高光相加即可.但环境光部分应当只计入一次.

阴影

如果进一步改进模型,我们可以考虑阴影.由于场景中可能存在物体挡住光源,所以计算一点的着色时,对每个光源方向我们可以做一次射线检测,如果命中了物体,说明在这一点处该光源被遮挡,计算时不考虑该光源即可.