Bresenham算法是DDA算法画线算法的一种改进算法。本质上它也是采取了步进的思想。不过它比DDA算法作了优化,避免了步进时浮点数运算,同时为选取符合直线方程的点提供了一个好思路。首先通过直线的斜率确定了在x方向进行单位步进还是y方向进行单位步进:当斜率k的绝对值$|m|<1$时,在x方向进行单位步进;当斜率k的绝对值$|m|>1$时,在y方向进行单位步进。
基本光照模型
本篇文章主要分析Direct3D中的固定功能光照模型。这个基本模型对经典的Phong模型进行了修改和扩展。关于不同的光照模型,将留到后续文章中介绍。在基本模型中,一个物体的表面颜色是放射(emissive)、环境反射(ambient)、漫反射(diffuse)和镜面反射(specular)等光照作用的总和。每种光照作用取决于表面材质的性质(例如亮度和材质颜色)和光源的性质(例如光的颜色和位置)的共同作用。用公式描述如下:
$$
surfaceColor = emissive + ambient + diffuse + specular
$$
透视校正插值
在《投影矩阵推导》中,我们提到在光栅化之前,我们需要对z坐标的倒数进行插值,这是因为在数学上,投影后的x和y,以及纹理坐标s和t,与z都不是线性关系,与1/z才是线性关系。本篇文章将围绕于此。
在3D渲染中,输入数据是一些primitive信息,包括顶点位置、颜色、纹理坐标等等。在光栅化阶段,primitive(一般为三角形)被转化成一系列的fragment(或者称为像素),此时每个fragment都有位置、颜色、纹理坐标这些属性信息,这些属性信息通过顶点属性用插值方法得到的。比如下面的primtive,输入数据中只有a,b,c三个顶点的信息,则三角形内部经过扫描转化得到的像素f的颜色则是通过插值得到,d是a、b的插值,e是a、c的插值,然后f又是d、e的插值。
法向量变换
模型的顶点的法向量一开始是定义在模型坐标系中的,在将模型布置在场景中后,根据光照模型计算颜色时需要用到顶点法向量,由于光照都是在世界坐标系中进行计算,这时用到的法向量也应该是定义在世界坐标系中。所以我们需要设法将顶点法向量从模型坐标系中转换到世界坐标系中。
我们已经知道通过缩放、旋转、平移三种基本操作合成的模型-世界变换矩阵可以将模型顶点坐标从模型坐标系中转换到世界坐标系中。那么这个模型-世界变换矩阵是否也可以将顶点法向量转换到世界坐标系呢?如果不行,那么需要找到一个可以完成这个任务的矩阵。
三角形的背面消隐
默认状态下,Direct3D认为顶点排列顺序为顺时针(观察坐标系中)的三角形单元是正面朝向的,顶点排列顺序为逆时针(观察坐标系中)的三角形单元是背面朝向的。
那么,如何判断一个三角形的绕序呢?让我们先从三角形的基本性质看起。
在左手坐标系中,当从三角形“正面”看时,经常以顺时针方向列出这些点,设这三个顶点为$v_1、v_2、v_3$。让我们标出下图中的三角形内角、顺时针边向量、边长。
视口变换矩阵推导
视口变换在投影变换之后,视口变换的作用是将投影平面上的点转换为屏幕上的点,这是一个缩放的过程。
投影矩阵推导
透视投影是3D固定流水线的重要组成部分,是将相机空间中的点从视锥体(frustum)变换到规则观察体(Canonical View Volume)中,待裁剪完毕后进行透视除法的行为。在算法中它是通过透视矩阵乘法和透视除法两步完成的。
经过相机矩阵的变换,顶点被变换到了相机空间。这个时候的多边形也许会被视锥体裁剪,但在这个不规则的体中进行裁剪并非那么容易的事情,所以裁剪被安排到规则观察体(Canonical View Volume, CVV)中进行,多边形裁剪就是用这个规则体完成的。所以,事实上是透视投影变换由两步组成:
1) 用透视变换矩阵把顶点从视锥体中变换到裁剪空间的CVV中
2) CVV裁剪完成后进行透视除法
观察矩阵推导
在流水线中,当物体从模型坐标通过世界矩阵变换到世界空间之后,它将通过相机变换从世界空间变换到相机空间。所谓的相机空间,就是以相机作为坐标原点的一个参考系,所以,从世界空间变换到相机空间,就是把物体从世界坐标系,变换到相机为原点的相机坐标系,如图所示。
C的变长参数
我们以实现函数printf的一个最简单版本为例,介绍如何以可移植的方式编写可处理变长参数表的函数。函数的声明形式为:
1 | void minprintf(char *fmt, ...) |
标准头文件
Direct3D的初始化(DirectX 9.0)
Direct3D的初始化过程可分解为以下步骤。
- 获取接口
IDirect3D9
的指针。 - 检查设备性能(
D3DCAPS9
),判断主显卡是否支持硬件顶点运算。 - 初始化
D3DPRESENT_PARAMETERS
结构的一个实例。 - 利用已初始化的
D3DPRESENT_PARAMETERS
结构创建IDirect3DDevice9
对象。