真实感图形生成:太阳系
一、实验内容简介
本实验利用球体参数方程生成了球体,利用三维变换实现球体转动的效果,并在此基础上对球体进行了纹理贴图,来模拟太阳、木星、地球的外观,同时实现了球体在可移动光源照射下的镜面反射效果以及消隐效果。
二、基本原理及实现算法
一、球体绘制
1、基本原理
绘制球体,本质上是绘制球面。而球面可以看成由很多个小的四边形平面构成的,这样就可以通过绘制这些小的四边形平面来构成整个球面,对于两极部分, 需要用三角形将球面两端封起来,如果把这些三角型看作是有两个顶点重合的四边形,问题就得到进一步的简化。因此只需知道球面上一些列点的空间坐标,就可以利用这些点来绘制四边形从而得到整个球面。
2、实现算法
球面上点的坐标可以利用参数方程获取。引入参数u,v,其中v是球面点与原点的连线与z轴正向的夹角,u表示连线在xy平面的投影与x轴正向的夹角,如下图所示:
球面参数方程可以表示为:
已知参数方程后,需要进行离散采样,分别设定u和v的步长:ustep、vstep,然后通过不同的u和v,求得坐标系中球面上点的实际坐标(x,y,z)。
3、实验结果
二、Phong光照模型
1、基本原理
- 理想漫反射:当光源来自一个方向时,漫反射光均匀向各方向传播,与视点无关,它是由表面的粗糙不平引起的,因而漫反射光的空间分布是均匀的。记入射光强为,物体表面上点
P 的法向为N ,从点P 指向光源的向量为L ,Kd 是与物体有关的漫反射系数由Lambert余弦定律,则漫反射光强为:Id=IpKd∗(L⋅N) 。 - 镜面反射光:对于理想镜面,反射光集中在一个方向,并遵守反射定律。对一般的光滑表面,反射光集中在一个范围内,且由反射定律决定的反射方向光强最大。因此,对于同一点来说,从不同位置所观察到的镜面反射光强是不同的。镜面反射光强可表示为:
Is=IpKs∗(R⋅V)n 。Ks 其中,是与物体有关的镜面反射系数,V 为视线方向向量,R 为反射方向向量,n 为反射指数,反映了物体表面的光泽程度,一般为1~2000,数目越大物体表面越光滑。镜面反射光将会在反射方向附近形成很亮的光斑,称为高光现象。 - 环境光:指光源间接对物体的影响,是在物体和环境之间多次反射,最终达到平衡时的一种光。我们近似地认为同一环境下的环境光,其光强分布是均匀的,它在任何一个方向上的分布都相同。在简单光照明模型中,我们用一个常数来模拟环境光,用式子表示为:
Ie=Ia⋅Ka ,其中:Ia 为环境光的光强,Ka 为物体对环境光的反射系数。
综合上面介绍的光反射作用的各个部分,物体表面上一点
2、实现算法
在用Phong模型进行真实感图形计算时,对物体表面上的每个点
3、实验结果
三、纹理贴图
1、基本原理
球面点可以用
该变换的反向变换是:
把
2、实现算法
首先,读取一张图片,将图片格式转为500*500,再将图片每个像素的RGB值保存下来。然后,对球面上的每个点用上面的公式计算其在
代码如下:
//纹理映射
p.v = (asin(p.z/radius)/pi + 0.5)*499.0;
p.u = (0.5 * ( atan2(p.y,p.x)/pi + 1.0 ))*499.0;
3、实验结果
四、Z-Buffer消隐
1、基本原理
当我们观察空间任何一个不透明的物体时,只能看到该物体朝向我们的那些表面,其余的表面由于被物体所遮挡我们看不到。消隐不仅与消隐对象有关,还与观察者的位置有关。本实验通过Z-buffer算法实现消隐。
2、实现算法
Z-buffer算法也叫做深度缓冲器算法,属于图像空间消隐算法。该算法有帧缓冲器和深度缓冲器。对应两个数组:帧缓冲器存储图像空间中每个可见像素的颜色值或亮度,深度数组存放图像空间每个可见像素的坐标。
该算法沿与投影面垂直的方向上发射一条射线,计算与空间物体交点的坐标,选择深度较小的进行显示。实验中,先将 Z 缓冲器中各单元的初始置设置为最小值。当要改变某个像素的颜色值时,首先检查当前多边形的深度值是否大于该像素原来的深度值(保存在该像素所对应的Z 缓冲器的单元中)。如果大于原来的 Z 值,说明当前多边形更靠近观察点,用它的颜色替换像素原来的颜色。伪代码如下:
3、实验结果
五、三维变换
1、基本原理
三维图形几何变换是二维图形几何变换的扩展。在三维空间中,用规范化齐次坐标
由于用齐次坐标表示,三维几何变换的矩阵是一个4阶方阵,其形式如下:
其中,
a、平移变换
参照二维的平移变换,我们很容易得到三维平移变换矩阵:
b、绕x轴旋转
三维空间的旋转相对要复杂些,考虑右手坐标系下相对坐标原点绕坐标轴旋转
c、绕y轴旋转
2、实现算法
//三维变换
void Sphere::UpdateTrans()
{
double Sina=sin(anga), Cosa=cos(anga), Sinb=sin(angb), Cosb=cos(angb);
Chang[0][0]=Cosa, Chang[0][1]=-Sina*Sinb, Chang[0][2]=Sina*Cosb;
Chang[1][0]=0, Chang[1][1]=Cosb, Chang[1][2]=Sinb
Chang[2][0]=-Sina, Chang[2][1]= -Cosa*Sinb, Chang[2][2]=Cosa*Cosb;
Matrix[3][0] = XLength;
Matrix[3][1] = YLength;
}
3、实验结果
如图所示,小球绕y轴旋转。
如图所示,小球绕x轴旋转。
参考文献:
- http://blog.csdn.net/majing19921103/article/details/45017547
- https://baike.baidu.com/item/Phong%E5%85%89%E7%85%A7%E6%A8%A1%E5%9E%8B/16858963?fr=aladdin
- http://bbs.csdn.net/topics/70286692