Chap 1--Introduction

1.1 Graphics Areas

1、公认属于图形学的领域:建模(Modeling),渲染(Rendering),动画(Animation)

2、相近的领域:人机交互(User interaction),虚拟现实(Virtual reality),可视化(Visualization),图像处理(Image processing),三维扫描(3D scanning),计算摄影(Computational photography)

1.2 Major Applications

视频游戏(Video Games),卡通片(Cartoons),视觉特效(Visual effects),动画电影(Animation films),计算机辅助设计/制造(CAD/CAM, computer-aided design/manufacturing),仿真(Simulation),医学成像(Medical imaging),信息可视化(Information visualization)

1.3 Graphics APIs

每个图形程序都会用到两个API,一个用于输出,一个用于从用户那里获得输入。当前主要有两种API模式:一种是采用集成方法,典型的是Java,把图形用户界面(GUI)集成在可移植的包中,这些包都是完全标准化的,并且作为语言的一部分;第二种则以Direct3D和OpenGL为代表,其中画图命令是软件库的一部分,软件库与某种语言(如C++)绑定,而用户界面(UI)则是独立的实体,在不同的系统中的UI可能也不相同,这种情况下编写可移植的代码并不容易。

1.4 Graphics Pipeline

图形流水线(graphics pipeline),是一个特别的软硬件子系统,能高效绘出透视图中的三维图元。流水线的基本运算是把三维顶点位置映射到二维屏幕位置,并对三角形进行明暗处理,使它们看起来比较真实并且看起来具有层次感。这个课题一度是计算机图形学的研究重点,但现在已经采用z-buffer算法几乎将此问题解决,它用特殊的内存缓冲区解决了暴力算法中存在的问题。


图形流水线中的几何运算,在四维坐标空间中几乎都可以实现,四维坐标由一般的三维几何坐标和利于处理透视问题的第四维齐次坐标组成。它是计算机科学中最精妙、最漂亮的构造之一,当然也是学习计算机图形学遇到的最大智力挑战。


图形流水线的速度与正在画的三角形数量有关。而因为交互能力比视觉效果更重要,所以在生成模型的过程中要尽可能减少三角形数量。另外,如果模型出现在远处,所需要的三角形数量就比模型在近处时少。这就意味着,在表示模型时要采用不同的细节等级(level of detail,LOD)。

1.5 Numerical Issues

幸运的是,现代计算机几乎都服从IEEE浮点标准,这为程序员处理数值问题带来了方便。IEEE浮点数中有三个特殊值:infinity(∞),表示大于任何数;minus infinity(-∞),表示小于任何数;not a number(NaN),表示无效数字,由结果未定义的运算得出,例如0除以0。大部分关于这三个值的运算都在我们意料之中,这里举出几个不太明显的:∞ - ∞ = NaN;∞ / ∞ = NaN;0 / 0 = NaN。

包含NaN的表达式规则如下:任何包含NaN的算术表达式,结果是NaN;任何包含NaN的布尔表达式,结果为假。

也许IEEE浮点标准最有用的是对除数为0的情况的处理。处理方式显而易见,但是我们需要注意的是,IEEE浮点标准中的0有两种表示法:+0和-0,两者区别虽然关系不大,但在某些情况下还是应该牢记这一点。

总之,IEEE浮点标准提供了对许多异常运算的解决办法,这就使得程序更加简单,更加健壮以及更加高效。

1.6 Efficiency

没有魔法能使代码更加高效。效率是对各方面认真权衡得到的,在不远的将来,一个好的程序员应该把心思放在存取方式上,而不是数值运算上,这是因为内存速度的提高跟不上处理器速度的提高。下面列出一些可选的优化策略:

1、尽可能以最直接的思路编写代码,尽量直接计算数据而不存储它。
2、在优化模式下编译。
3、使用性能分析工具找出关键的瓶颈。
4、检查数据结构以寻找调整数据位置的方法。如果可能,使数据单元大小和目标体系结构的高速缓存/页面大小匹配。
5、如果性能分析工具表明数值计算中存在瓶颈,则检查编译器生成的汇编代码,找出效率低的原因,重写源代码以解决发现的任何问题。

这些步骤中最重要的是第一步。很多“优化”使代码更加难读却不提高效率;另外,花时间在预先的代码优化上,要比纠正bug和添加特色要好;还有,读旧的文献时要谨慎,有些传统的小技巧已经过时了,比如现在已经不需要用整数运算替代浮点数运算了,因为现在的CPU处理浮点数运算已经和处理整数运算差不多快了;最后,在所有情况下,在具体机器和编译器上优化后,都要经过性能分析,以确定优化有没有效果。

1.7 Designing and Coding Graphics Programs

1.7.1 Class Design

任何图形程序的关键部分是针对几何实体(如向量和矩阵)以及图形实体(如RGB颜色和图像)都具有比较好的类或者例程,这些例程应尽可能简洁和高效。下面列举一些应包括的基本类:

vector2:二维向量类,它将x和y存储在长度为2的数组中以支持索引操作。它还应包括向量加法,向量减法,点积,叉积,标量乘法和标量除法等。
vector3:三维向量类,与vector2类似。
hvector:含4个分量的齐次向量。
rgb:含三个分量的RGB颜色,与三维向量类似。
transform:4*4变换矩阵,应该包括矩阵乘法,以及求位置,方向以及表面法向量的成员函数。
image:由RGB像素构成的二维数组,包含输出操作。

另外,也可以考虑加入区间、标准正交基、坐标系等类。

1.7.2 Float vs. Double

现代体系结构表明,减少内存使用并保持一致的内存存取是提高效率的关键。这表明应使用单精度类型(float),但是如果要避免数值问题,则应采用双精度类型(double)。对二者的权衡取决于实际程序,不过在类定义中设置默认值是个好习惯。

1.7.3 Debugging Graphics Programs

随着编程者越来越有经验,他们使用传统调试器(采用步进运行观察变量值的调试方法)的次数会越来越少,一是因为复杂程序使用传统调试器更麻烦,二是因为最难发现的错误都是概念上的错误,即实现的目标就错了。

在图形学程序中,有一种非常实用的调试方法可供选择,即先构建一幅图像,并观察有什么问题,然后针对产生问题的可能原因作出一种假设,并进行验证。这有点像科学探究实验的步骤,这种方法有时很实用的关键原因在于,我们不是必须找到错误值,或者真正确定是概念错误。相反,我们只是通过实验缩小概念错误的范围。一般仅需几次尝试就可以找到问题,这种调试是很享受的。

在很多情况下,图形学程序获得调试信息的最简单的方法是输出图像本身。如果你想知道一些变量的值(这些变量来自于那些每个像素都会运行的计算),那你可以暂时修改你的程序,直接将结果值复制到输出的图像中,并跳过剩余的,本应执行的计算过程。

另外还有一些情况,前述的探究方法可能导致矛盾的结果。但这时用传统调试器从头开始步进执行仍然是不现实的,因为图形学程序中经常有许多重复执行很多次的代码段,而最难发现的bug往往是复杂的输入引起的。这时我们可以给bug“设置陷阱”:首先确保程序是确定性的——用单线程运行并保证所有随机数已经由种子产生;然后观察存在bug的像素或者三角形,接着添加一些语句,并使这些语句只在处理这些你怀疑的case时执行,再继续观察程序运行情况。

通常在程序崩溃时,用传统调试器可以找到崩溃的位置,这时可以在程序中添加断言(assert)并重新编译,从而找出程序出错的位置。断言是一种宏,如果它包含的布尔表达式的结果为假,则终止程序。在程序开发与调试过程中,应该多使用断言。如果你曾经用过,就让它留在代码中,以后再出现bug时,它就会起作用。注意在优化运行中,需要定义预处理变量NDEBUG来关闭断言。应该使用断言意味着应该避免使用传统的步进调试,因为传统调试过程中无法加入这样有价值的断言。

你经常无法理解程序在做什么,因为在它最终出错之前,它会计算许多中间值。我们可以将程序运行过程可视化从而方便我们的调试,花费一些时间来编写代码,将程序运行的内部状态可视化。这样做是值得的,因为当我们需要优化程序的时候,我们能够很容易理解程序的行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值