hyde
路人甲
路人甲
  • 注册日期2003-09-24
  • 发帖数555
  • QQ
  • 铜币1457枚
  • 威望0点
  • 贡献值0点
  • 银元0个
阅读:1353回复:0

3D图形编程指南9再续 - 光线

楼主#
更多 发布于:2004-04-27 14:16
当然,这一过程是循环进行的。为了计算正确的光照路线,还要产生出其他的反射射线。在实际使用时,要对光线的反射次数进行一定的限制,不能无限次的反射下去,经过多次反射之后,有些光线就可以忽略不记了。
  环境反射还要有一个系数来进行加权,因为物体的反射能力是有所区别的。尽管在实际生活中这一系数对于光源和反射光都是一样的,但我们通常还是将它们分开来进行考虑,这样可以对最终的图象结果进行更好的处理。图8.19是一个通过递归光线跟踪方法计算的场景的效果:


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><B><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image606.gif"></B></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.19 考虑阴影和环境反射的光线跟踪效果</B></FONT></TD></TR></TABLE>
  在图8.19中,反射的效果已经十分接近真实情况了。要注意一点,一些反射所反映的场景图象是我们所无法直接看到的。既要模拟虚拟世界中的额外物体,又要计算不能直接看到的物体间的光线作用效果是很耗费系统资源的。在这种情况下,我们可以将可见物体放置在一个立方体中,然后把用来描绘不可见环境的静态图象以纹理的形式贴附在它的内部多边形上。这样一来,既避免了对额外效果的模拟(因为纹理图象都来自真实环境),又减少了循环的次数。
  通常,光线跟踪算法可以通过很简单的语句就能实现,它被编制成一个统一的框架,应用于不同的任务,如可见性判断、阴影、以及光照模型的其他部分。程序清单8.2中列出了一个主跟踪路径,用于进行当前的渲染。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image607.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>程序清单8.2 递归光线跟踪算法</B></FONT></TD></TR></TABLE>
  我们还可以将光线跟踪算法进行扩展,进行其他光照效果的的计算,例如穿过半透明物体的光线反射。
  我们还可以给上面的算法加入一个计算光线亮度随距离衰减的函数,这样就可以考虑光线衰减问题了。我们还经常要对表面的无规律则性进行模拟。这时,可以给表面分配一个纹理图样,使它的每一部分都有不同的反射系数。为了更好的对表面的无规律性进行模拟,还可以使用凹凸贴图(bump-map)。在使用它时,物体表面的法向量是杂乱无章的,因此反射也就有不同的方向。
  我们可以将以上这些效果以及其它可能的效果混合在光线跟踪框架中,这样产生出来的效果会十分逼真。
  但是,使用递归光线跟踪方法时也会有一些问题出现,它们直接导致了在对一幅光线跟踪图象进行观察时会出现一些问题。首先,我们在处理镜面反射时要依赖于不同的光线属性。在光源方面,我们通常设置一个近似的函数来产生较强的光线。另一方面,环境的影响则通过反射射线来进行计算。所有由光源产生的高光的大小最多只能有一个像素。换句话说,我们在由光源产生高光的情况下对表面的不理想性进行调整,而不是在由反射光线产生高光时进行调整。结果,反射的效果往往就超出了实际的情况,变得非常的好。
  在使用修正的Phong照明模型来计算环境反射的影响时,我们还会遇到另一个基本的问题, 那就是不用考虑漫反射光线对环境反射的影响。所有的漫反射表面反射的光线都会发散到所有的方向,因此总会有一些光线照射到使用照明模型的点上。对于这些光线,我们的模型将不予考虑。既然漫反射的光线可以照射到一些给定的点上,那我们就应该对所有方向都发射出一束射线来检测是否对光照效果有作用。由于这一过程也是一个循环进行的过程,因此在计算上是非常难以实现的。在下面的讨论中,我们将主要考虑解决多个漫反射表面的照明问题。
  综上所述,光线跟踪算法是计算机图形学中一个十分重要的方法,它对计算量的要求使得它在一些有较多交互性要求的任务中的可用性大大降低。然而当我们将场景视觉效果放在首要位置,而又没有交互性存在时,这种方法是非常有效的。

<B>8.5、辐射度</B>
  在前面的讨论中,光线跟踪通常都忽略了漫反射表面的影响,或者有时又太精确了一些,而我们通常又都使用一个环境光常量来对这种影响进行补充。然而,在许多实际情况下,这些影响又往往是非常重要的。例如,考虑图8.20中一个完全的漫反射表面B。它的方向背对着图中唯一的一个光源,这样, 根据漫反射照明模型,除非是有环境光存在,否则它将是漆黑的。在表面B的旁边还有一个漫反射表面A,而在实际情况下,A反射的光线总会有一些照射到表面B上,从而将它照亮。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image608.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.20 漫反射表面对照明的作用</B></FONT></TD></TR></TABLE>
  为了解决这一问题,计算机图形学借鉴了热转移理论的一些内容。它的基本思想是,在一个靠近的环境中,能量分布是平衡的。现在我们假定有一个表面,它既能发出光线又能反射光线,由一个小面片发出的光线的量我们称之为面片的辐射度(radiosity),它等于面片本身发出的光线加上由其他面片反射的光线。可以用下式来表示:


<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image609.gif"></TD></TR></TABLE>
  公式中,B表示面片的辐射通量密度,E是它的辐射强度,K表示反射能力。这样,当场景由一系列的小面片组成时,我们假定面片的大小足够的小,使得穿过面片的辐射度为一个常量,那么上面的公式就可以用下面的公式来代替:

<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image610.gif"></TD></TR></TABLE>
  公式中,<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image611.gif">是一个系数,它表示有多少光线从面片<I>j</I>到达面片<I>i</I>。正如我们所看到的,辐射度方法允许我们对光源和反射表面进行统一的处理。一个<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image612.gif">为非0值的面片就是一个光源。系数<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image613.gif">被称为构成因子(form factor),它们本质上表示了场景中的几何体。为了计算构成因子,我们必须要考虑两个面片的方向,它们的范围以及它们是否被其他面片所遮挡。这是一个十分复杂的几何问题,但是一旦计算出了构成因子,场景中每一个面片的辐射度都可以通过解一个线性方程式来得到。将所有未知的辐射度B组合在一起,我们可以得到下面的线性等式:


<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image614.gif"></TD></TR></TABLE>
  上面的公式写成矩阵形式如下:


<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image615.gif"></TD></TR></TABLE>
  要注意,如果使用了单色模型,那么上面公式中的每一个元素都是标量,如果使用的是RGB模型,那么每一个元素都是三维矢量,也就是实际上有三个矩阵等式,分别对应于每个颜色分量。通过解上面的等式,我们可以得到每个表面面片的辐射度,接下来,在绘制每一个面片时,我们就可以根据辐射度数值来进行场景的可见性处理。
  还有一点要注意,那就是我们假设通过每一个面片的辐射度为一个常量,这实际上是放宽了对条件限制。这种对条件的放宽,它的影响只有在面片足够小时才可以被忽略。这样,每一个实际的场景都必须要分割成许多小的部分,也就增加了矩阵的大小,当然也增加了求解的时间。但是从另一个方面来考虑,辐射度仅仅考虑了所有方向上的漫反射,并且它对于观察者的位置是没有约束的。因此,当场景中的几何体和灯光都是静态的时,我们可以再次使用同样的辐射度方法来进行计算。
  总之,辐射度方法对于提高场景的真实感是非常有用的。但是,在定义中我们可以看到,它没有考虑到镜面反射问题,并且也很难在辐射度方法中加入对它们的计算。通常,我们都将辐射度方法作为光线跟踪算法之前进行的一个预处理过程。而这样做也并不是没有价值的,因为某些镜面高光正是由漫反射产生的,而镜面反射也可能导致漫反射的产生。由于在这两个处理过程中实现所有的效果时不现实的,因此许多实际的应用往往只限于一些普通的效果。
<B>
8.6、在世界到屏幕(<I>world to screen</I>)中观察照明中观察照明</B>
  在世界到屏幕中观察照明与在屏幕到世界中观察照明是很不一样的,它们的效果往往会大打折扣。让我们回顾一下我们所使用的方法,将图元投影到屏幕空间来创建一幅虚拟世界的图象,然后将它们光栅化为图象位图,这样我们就得到了一幅虚拟世界的图像。在进行光线跟踪处理时,我们将照明模型应用与世界中每一个可见的点上。在世界到屏幕中观察照明也可以采用类似的方法。当我们在将一个点放置在图象中之前对一个图元进行光栅化处理时,我们可以选择使用照明模型从而调整像素的颜色。有一些问题会立即显现出来。一般的世界到屏幕算法以及一些特殊的光栅化算法都要求一定的速度和相应的帧速。这些算法都将处理过程定位在对单个像素的处理上。通过对每个像素进行照明计算,提高了计算的复杂性。第二,在使用从后到前(back to front)光栅化处理方法来计算隐藏表面时,我们可能会对某些像素重新绘制很多此,这样,大量的计算量就耗费在了一些无用的像素上。在这方面,有一些隐面消除算法已经试图去避免这些情况的发生。但是,基本的问题仍然是按照每个像素进行光栅化,这样的计算量还是很大,我们还是需要考虑全局照明效果。
  处理局部照明的一般方法是只对图元的几个特殊地方进行照明的计算,而在其它地方进行内插运算,这就叫做图元的明暗处理。我们已经在第三章中看到了使用内插进行明暗处理的多边形。对于一些全局照明效果,例如阴影和环境反射,在世界到屏幕进行观察不会在通用的框架中对它们进行处理,这些都要进行特别的处理才能达到,或者不予考虑。
  让我们先来考虑一些明暗处理算法,之后,我们主要将讨论用于计算全局照明效果的一些技术。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image616.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.21 平面明暗处理</B></FONT></TD></TR></TABLE>
  很明显,明暗处理的类型依赖于所使用的照明模型以及我们准备对一些条件所采取的放宽程度。例如,如果我们假设对多边形采取统一的照明,我们就可以对每一个多边形只计算一个点,然后使用得到的颜色进行光栅化处理。这一过程我们成为环境或平面明暗处理(ambient or flat shading)(见图8.21)。在环境照明情况下,上述假设一般都可以实现,但是在漫反射表面和Bouknight照明模型情况下上述假设只能在多边形是一个平面的情况下在能够实现,也就是说,对于曲面它是没有用的,并且在场景中只有方向光(所有的光源都有一定的作用距离)也是没有用的。让我们回忆一下这个照明模型的公式:


<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image564.gif"></TD></TR></TABLE>
  照明依赖于表面法向量(<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image617.gif">)和指向光源的方向矢量(<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image618.gif">)。当我们用多边形来对曲面进行近似时,法向量不再是一个常量(见图8.19)。如果又一个点光源的话,那么在多边形上指向光源的方向也会发生变化。在这种情况下,如果我们还是假设照明是一个常量的话,就会导致错误的结果。但是,由于计算机图形学是对真实环境的一种再现过程,而不是简单的进行复制,那么我们当然可以使用这种有一定失真的结果。
  这样,即使在Bouknight和Phong照明模型情况下,我们仍然可以决定使用环境明暗处理。在后一种情况时,如果我们碰巧在镜面高光的位置进行了计算,那么整个多边形都将是高光,这样就会严重失真。
  使用平面明暗处理方式的多面体由于人眼的视觉特性会出现一种马赫带效应,我们可以在图8.21中清楚的看到。尽管每一个多边形都有统一的颜色,但是在多边形边缘的地方,我们感觉到较暗的一边会变得更暗,而较亮的地方会变得更亮。当亮度有限时,人眼在接收光线时会对相邻的东西有所抑制。这样,对较暗一边光线的接收就会被相邻的较亮的一边所抑制,因此就会显得更暗了。而对较亮一边光线的接收没有被它的近邻所抑制,因此有较亮的信号响应。对于平面明暗处理,就会出现比较明显的轮廓,这并不是我们所希望的。
  因此,我们还有另外一种方法来提高画面质量,它就是<I>Gouraud</I>明暗处理。这种方法对多边形的顶点计算照明效果,然后对亮度进行内插。图8.22显示了这种方法:


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image619.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图</B><B>8.22:Gouraud明暗处理</B></FONT></TD></TR></TABLE>
  这种明暗处理对于描述漫反射的Bouknight照明模型同样适用。通过对亮度值进行平滑,它可以将曲面近似时出现的小块现象避免掉。
  为了计算照明效果,我们首先要找到顶点的法向量。当我们用一些小平面对曲面进行近似时,顶点的法向量可以通过对小平面的法向量求平均的方法来获得,如下图所示:


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image620.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.23 使用平面多边形来近似曲面</B></FONT></TD></TR></TABLE>
  这种明暗处理方法还允许我们模拟漫反射表面在点光源不均允照明情况下的效果。但是,它并不适合于镜面反射和Phong照明模型。根据定义,内插明暗处理方法只允许在多边形表面对亮度进行线性的改变。而镜面反射的亮度变化却是非线性的:


<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>

<TR align=middle>
<TD><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image579.gif"></TD></TR></TABLE>
  这样,当镜面反射出现在多边形内部时,我们就会将它完全忽略掉,或者当高光出现在多边形的顶点处时,使用线性内插就会得到错误的结果。和环境明暗处理时的情况类似,当多边形较小或者对品质的要求较低时,这种方法还是可行的。
  当我们需要正确的描绘镜面反射效果时,我们就要使用Phong明暗处理方法(不要与Phong照明模型相混淆)。只用这种算法,可以有效的在每一个光栅像素计算照明模型并对模型的一个成分在多边形上进行内插。让我们再看一下上面的照明模型公式。我们可以看到,计算时要用到法向量,这样,由于我们经常使用多边形来近似曲面,就可以对多边形的方向量进行内插,然后用它来计算每一点的照明。(见图8.24 (c))。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image621.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.24 (a)环境、(b)Gouraud及(c)Phong明暗处理</B></FONT></TD></TR></TABLE>
  法向量的每一个成分被单独的进行内插,这样就会得到多边形上每个点的近似方向亮。我们必须注意,在计算时使用单位法向量是很重要的。在进行内插时,也要将每一点的法向量进行归一化。但是,在每一点都使用内插法向量来计算照明,计算量还是很大的。然而,正如在我们第一次考虑照明模型时所看到的那样,可以使用半程矢量来简化计算并将观察者的位置置于无穷远处。我们可以预先计算好<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image622.gif">(或者是替代公式中的<IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image623.gif">),然后在执行时用表格来进行查询。
  前面介绍的明暗处理方法允许我们在世界到屏幕观察框架中引入照明模型。但是,场景中多个物体的出现可能会要用到其它的一些照明效果,如阴影、环境反射等。我们还需要解决前面讨论过的漫反射表面的相互照明问题。辐射度算法可以用于对世界到屏幕进行预先处理。当场景中的几何体和照明不随帧的变化而变化时,它还可以在多个帧中多次使用,例如我们要产生一个飞跃的虚拟场景时。通常,当要求场景中的物体有一定的交互性时,在运行期间计算其它全局照明效果将很难实现,因此就需要对它们进行预先的处理。
  在所有的全局照明效果中,我们将只讨论阴影和环境反射。计算阴影有许多种算法。我们通常将它们分为两组。第一组预先计算描绘阴影所需的几何信息。第二组在场景光栅化时计算动态阴影效果。因此,前一组算法是不能计算变化场景的动态效果的。
  有两种方法来预先计算阴影。最常用的一个是将场景细分为许多部分,使得对于每一个点光源每个图元都能被完全照亮或者完全隐藏。另一种方法在纹理中存储阴影信息。后一种方法需要对每一个图元都设置一幅特殊的纹理,因此在有些情况下时不可行的。
  预先计算阴影,我们就要解决可见性问题。在光源处可见的图元部分是可以被照亮的,而其它部分就应该有阴影存在。图8.25描绘了一个阴影域。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image624.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.25 阴影域</B></FONT></TD></TR></TABLE>
  如图中所示,被照亮的多边形在空间中产生了一定的阴影范围。这个范围形成了一个多面体,阴影有它的顶部开始产生,位于这个多面体内的多边形部分都是有阴影的。而其它的多边形都可以被这个多面体裁剪为两个部分,一部分完全是阴影,另一部分则完全被照亮。被照亮的多边形还要标明是被哪个光源照亮的,这样在进行光栅化处理时,就可以明确知道每个多边形是由哪个光源照亮的。
  这种划分是非常复杂的,但是我们可以利用合成场景的一些特性来减少计算量。例如,一个多边形往往都是一个物体中的一部分,这样,我们就可以直接对这个物体使用阴影范围来进行分割。减少阴影范围的数量也可以减少处理量。我们还必须明白,这种方法只是运行前的一个预处理步骤。这样,减少分割的数量就要比性能更重要。
  使用BSP树算法来计算阴影范围是很有效的。使用BSP树,我们可以很容易得到按照从后到前顺序排列的多边形。同样,也很容易得到从前到后的顺序。我们必须在循环调用时将顺序翻转过来。对于某个光源的一个从前到后的顺序显示了哪个多边形能够为其它多边形产生阴影。很明显,在前面的多边形会对后面的多边形产生阴影,这样,列表中的多边形会对它后面的多边形产生阴影,但是不会影响到其它分支的多边形。我们可以使用阴影范围算法并沿着列表执行必要的分割。当我们将任何一个多边形分为阴影区和照亮区之后,所有的这些区域仍然属于同一个平面,并且可以被联合存储在树中原先的地方。
  其它产生阴影的算法也包括了解决可见性的问题 。阴影Z-buffer算法(shadow Z-buffer)是对一般隐面消除算法的扩展。见图8.26。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image625.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.26 阴影Z-buffer</B></FONT></TD></TR></TABLE>
  在图8.26中,有两个Z-buffer,其中一个称为光线Z-buffer。如果我们在渲染场景之前计算光线Z-buffer,我们可以调整真正的基于光栅的Z-buffer使它能够解决阴影。当我们要将一个点放置在屏幕上和Z-buffer中时,我们可以找到它在光源前面的平面上的投影,并检查这个投影的Z坐标是否是存储在光线Z-buffer中的那个。如果真是这样的话,这个点对于光源就是可见的, 我们就可以在主图象中对这个进行照明。例如在图8.26中的点A。当我们检查它对光源的可见性时,我们在光线Z-buffer中定位一个比遮挡点的Z坐标较小的位置。这样,点A就有阴影。另一方面,点B就不是这样,我们在对它进行光栅化时就要考虑它的照明问题。
  这个算法的一个明显的缺点是要对每一个光源都定义一个光线Z-buffer。同时,将额外的处理过程引入光栅化的内部循环中,提高了程序的复杂性,但是由于自身的特性,Z-buffer算法经常会覆盖掉一些像素先前的值。这样,我们可能会对一些不会在最终的图象中描绘出来的点来计算它的照明和阴影。解决这一问题的一个方法是先对图象进行光栅化处理然后加入阴影计算。这样,我们就只对出现在最终图象中的点才计算它的阴影信息。还必须注意,由于照明模型是附加的,我们可以对所有的光源暗中使用同一个光线Z-buffer。
  在光线跟踪部分,我们已经讨论过使用正规的光线跟踪框架来解决环境镜面反射问题。本质上,我们在镜面反射的方向上解决可见性问题从而找到由一个光亮表面产生的环境反射。同样,我们在一个不同的框架中也可以实现世界到屏幕的观察。见图8.27。


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image626.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.27 计算环境映射</B></FONT></TD></TR></TABLE>
  图8.27描绘了一个镜面反射面片。很明显,由于它的镜面反射能力,这个面片可以显现出环境的反射。因为反射方向与入射光线关于法向量成镜像关系,所以我们可以假想一个观察者(如图中所示),根据它来计算一个单独的图像,然后将这幅图象一纹理的形式应用到原始观察的处理过程中。
  观察算法的多重引用是很耗费计算量的,因此,我们可以预先计算好环境反射并保存在纹理信息中。必须注意,一般的纹理映射是与观察无关的,而环境映射却是与观察有关系的。当观察方向改变时,我们就要调整纹理映射使它随之改变,这样才不会影响场景的真实感。这种方法在几何关系上不一定是正确的,但却能使我们感受到环境反射的效果。
  在有些情况下,我们可能需要动态的并且几何关系也是正确的反射效果,比如场景中的一面镜子。这样,才能对场景中的镜子进行正确的模拟。(见图8.28)


<TABLE cellSpacing=0 cellPadding=2 align=center border=0>

<TR align=middle>
<TD colSpan=3><IMG src="mk:@MSITStore:E:\3D图形编程指南.chm::/3D图形编程指南/image/8.1/Image627.gif"></TD></TR>
<TR align=middle>
<TD colSpan=3><FONT color=#cccccc><B>图8.28 一个镜面反射体的几何模型</B></FONT></TD></TR></TABLE>
  在图8.28中,我们对场景引入了一个镜像拷贝,从而对镜面反射体进行了很好的模拟。对于观察者来说,他的感觉是看到了场景的反射效果。当然,具体执行的图像精度要视我们的程序和所要达到的目标而定。

  <B>小结</B>
<FONT face=楷体_GB2312>  <FONT color=#993300>照明处理在计算机图形中是非常重要的。通常,每一种颜色都可以用它在一定范围内的能量分布来进行描述。考虑到人眼的视觉特性,我们可以简单的用三原色(红、绿、蓝)来对颜色进行描述。当场景中有多个物体时,我们就会面临一个全局照明的问题,也就是物体以不同方式反射的光线也会照亮其它的物体。光线跟踪算法可以计算一些全局照明效果,如阴影、镜面反射等。辐射度算法可以解决所有全局照明中的漫反射相互影响问题。局部和全局照明在世界到屏幕中进行观察是都是很复杂的。在这种观察方法中,局部照明可以用明暗处理方法来进行近似,而全局照明效果依赖于一些特殊的附加技术。</FONT></FONT><FONT face=楷体_GB2312><FONT face=楷体_GB2312><FONT face=楷体_GB2312>

</FONT></FONT></FONT>
喜欢0 评分0
夜落了,风静了,我喜欢一本书,一杯茶,一粒摇曳的烛光...
游客

返回顶部