计算机图形学课程设计报告 简单光照
图形学光照实验报告
glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib); glVertex2i (i+x0,-y+y0);
}
for(i=-y;i<=y;i++)
{
for(int i=-x;i<=x;i++)
{
mColor=Phong(x0,y0,r,i+x0,y+y0);
glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib); glVertex2i (i+x0,y+y0);
glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib); glVertex2i (i+x0,-y+y0);
deltax += 2;
deltay += 4;
x++;
y--;
}
CirclePt( x0, y0, x, y, mColor);
}
}
//根据中点圆算法填充圆域
void FlatCircle(int x0, int y0, int r, Color mColor)
{
int x,y,deltax,deltay,d;
x = 0;
y = r;
deltax = 3;
deltay = 5-r-r;
d = 1-r;
glColor3ub (mColor.Ir, mColor.Ig, mColor.Ib);
计算机图形学课程设计报告——范文
《计算机图形学》课程设计报告题目名称:专业班级学号姓名指导教师年月日Solar System(太阳系)软件工程专业学生王洋指导老师李征[摘要]太阳系(Solar System)是以太阳为中心,和所有受到太阳重力约束的天体的集合体,主要包括太阳,八大行星,以及卫星.此课题模拟太阳系围绕太阳运转的模型,以太阳,八大行星和月球形成大致的体系结构,以VC6.0为平台用OpenGL基础知识实现从不同角度观测太阳系.关键词:OpenGL VC6.0 太阳系运转角度一、实验名称:Solar System(太阳系)二、实验的目的和要求:1.熟悉OpenGL基础函数2.通过程序模拟太阳系运行3.实现改变视角观测太阳系三、实验的环境:1.硬件环境:CPU Intel Pentium D ,1G内存2.软件环境:操作系统:Windows xp SP2编译软件及版本:vc6.0 OpenGL环境四、系统描述1.太阳太阳是恒星,能够自转,体积是太阳系中最大的,能够发光,处于太阳系中心位置.2.八大行星八大行星按与太阳距离从近到远分别为:水星,金星,地球,火星,木星,土星,天王星,海王星,各有各的大小,其中以木星最大,以各自不同的公转速度绕太阳运行,并自转.3.月球月球是围绕地球旋转的卫星.体积是系统中最小的,旋转周期比较快。
五. 理论基础:用windows api创建窗口,使用OpenGL绘制函数绘制球体,实现位图文件读取,并转换为纹理,使用系统时间控制球体转动,设置视点视角,通过改变视角从不同角度观测.所使用的计算机图形学理论基础:1.3D管道中的几何变换旋转矩阵行向量为该矩阵坐标系在原坐标系上的坐标,列向量为原坐标系的向量在本旋转矩阵坐标系上的坐标。
旋转是欧氏变换;旋转、放缩是线性变换;旋转、放缩、平移是仿射变换;旋转、放缩、平移、透视投影是射影变换。
线性变换在四维空间,仿射变换在三维空间,射影必须采用摄像坐标系,仿射变换是到自身的一类变换.齐次坐标系就是将一个原本是n维的向量用一个n+1维向量来表示。
计算机图形学实验报告4
计算机图形学实验报告4一、实验目的本次计算机图形学实验旨在深入了解和掌握计算机图形学中的一些关键概念和技术,通过实际操作和编程实现,提高对图形生成、变换、渲染等方面的理解和应用能力。
二、实验环境本次实验使用的软件环境为_____,编程语言为_____,硬件环境为_____。
三、实验内容1、二维图形的绘制使用基本的绘图函数,如直线、矩形、圆形等,绘制简单的二维图形。
通过设置线条颜色、填充颜色等属性,增强图形的表现力。
2、图形的几何变换实现图形的平移、旋转和缩放操作。
观察不同变换参数对图形的影响。
3、三维图形的生成构建简单的三维模型,如立方体、球体等。
应用光照和材质效果,使三维图形更加逼真。
四、实验步骤1、二维图形的绘制首先,在编程环境中导入所需的图形库和相关模块。
然后,定义绘图窗口的大小和坐标范围。
接下来,使用绘图函数按照指定的坐标和参数绘制直线、矩形和圆形。
最后,设置图形的颜色和填充属性,使图形更加美观。
2、图形的几何变换对于平移操作,通过修改图形顶点的坐标值来实现水平和垂直方向的移动。
对于旋转操作,根据旋转角度计算新的顶点坐标,实现图形的绕中心点旋转。
对于缩放操作,将图形的顶点坐标乘以缩放因子,达到放大或缩小图形的效果。
3、三维图形的生成首先,定义三维模型的顶点坐标和三角形面的连接关系。
然后,设置光照的位置、颜色和强度等参数。
接着,为模型添加材质属性,如颜色、反射率等。
最后,使用渲染函数将三维模型显示在屏幕上。
五、实验结果与分析1、二维图形的绘制成功绘制出了各种简单的二维图形,并且通过颜色和填充的设置,使图形具有了更好的视觉效果。
例如,绘制的矩形和圆形边缘清晰,颜色鲜艳,填充均匀。
2、图形的几何变换平移、旋转和缩放操作都能够准确地实现,并且变换效果符合预期。
在旋转操作中,发现旋转角度的正负会影响旋转的方向,而缩放因子的大小直接决定了图形的缩放程度。
3、三维图形的生成生成的三维模型具有一定的立体感和真实感。
计算机图形学实验03_光照模型
北方工业大学计算机图形学课程实验报告题目:实验三光照模型学院:计算机学院专业:数字媒体技术指导教师:学生班级:学生学号:学生姓名:教师评定:学号:班级:姓名:实验报告3 光照模型一.实验目的1.熟悉OpenGL图形库;2.掌握光照模型算法。
二.实验环境1.软件环境:操作系统:WinXp应用软件:VC6.0,OpenGL2.硬件环境(查看自己的机子)CPU: Intel PIV 2.80GHz内存RAM: 1GB显卡:NVIDIA GeForce7650,256M显存三.实验内容1写程序实现一个聚光灯围绕立方体旋转程序。
要求给出RenderScene()函数。
void RenderScene (void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清楚颜色数据和深度数据(清屏)glColor3f(1.0,1.0,1.0);glLoadIdentity(); //初始变换矩阵为单位矩阵glTranslated(0,-1,-5); //平移0,0,-5向Z负方向平移5个单位glPushMatrix(); //压缩矩阵,设定光源的位置glDisable(GL_LIGHTING);glRotatef(yRot, 0, 1, 0); //光源的旋转glTranslatef(light_change[0],light_change[1],light_change[2]); //光源的位置glTranslatef(light_position[0], light_position[1],light_position[2]); //光源位置glutSolidSphere(0.1, 4,4);//利用库函数绘制一个半径为1的球体。
表示光源在这里glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0, GL_POSITION, light_position);glPopMatrix();light_direction[0] = -light_change[0];light_direction[1] = -light_change[1];light_direction[2] = -light_change[2];glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);glPopMatrix(); //光源设置完毕glPushMatrix(); //压入变换矩阵那// glutSolidSphere(1, 30,30);//利用库函数绘制一个半径为1的球体。
计算机图形学课程设计
《计算机图形学》课程设计报告学院:专业:班级:姓名:学号:指导教师:年11 月15 日一、课程设计报告内容说明:1 、直线:1.1 点生成直线利用for 循环,用pDC->SetPixel(int x,int y,RGB(a,b,c))像素函数画出直线。
1.2 DDA :根据直线的微分方程来产生直线,即dy/dx=△y/△x=(12y y -)/(12x x -)=k其中(1x ,1y )、(2x ,2y )是直线的两个端点坐标。
DDA 算法的原理是增量法,即使x 和y 同时以很小的步长增长,每次增长量与x 和y 的一阶导数成正比。
直线的一阶导数是与△x 和△y 成正比的函数。
可以将x 和y 各递增ε△x 和ε△y 来产生线,ε是很小的量。
从当前画线任意点的位置(i x ,i y )上分别递增两个增量ε△x 和ε△y ,就可以得到直线增长的下一个(1+i x ,1+i y )的坐标位置公式如下1+i x =ix +ε△x1+i y =i y +ε△y1.3 金刚石将圆分为20份,利用直线生成的MoveTo 和LineTo 函数,使每个点与其他点相连。
展示图形为:点生成直线、数值微分法画直线、金刚石 2、曲线2.1 直角坐标系:写出参数表达式后,利用MoveTo 和LineTo 函数,连接各点。
如:正弦曲线:参数方程如下 x_SIN=1000*t; y_SIN=1000*sin(t);极坐标系:写出参数表达式后,利用MoveTo 和LineTo 函数,连接各点。
如:四叶图:参数方程如下r_SIYE=5000*sin(2*t); x_SIYE=r_SIYE*cos(t); y_SIYE=r_SIYE*sin(t);2.2 以实际工作中应用较多的参数样条曲线为例:参数样条曲线定义:给定n+1个控制点Pi (i =0,1,2,…,n ),n 次B 样条曲线段的参数表达式为: 。
依次用线段连接控制点Pi (i =0,1,2,…,n )组成的多边形称为B 样条曲线控制多边形。
计算机图形学第五次实验报告
《计算机图形学》实验报告实验十一真实感图形一、实验教学目标与基本要求初步实现真实感图形, 并实践图形的造型与变换等。
二、理论基础运用几何造型, 几何、投影及透视变换、真实感图形效果(消隐、纹理、光照等)有关知识实现。
1.用给定地形高程数据绘制出地形图;2.绘制一(套)房间,参数自定。
三. 算法设计与分析真实感图形绘制过程中, 由于投影变换失去了深度信息, 往往导致图形的二义性。
要消除这类二义性, 就必须在绘制时消除被遮挡的不可见的线或面, 习惯上称之为消除隐藏线和隐藏面, 或简称为消隐, 经过消隐得到的投影图称为物体的真实图形。
消隐处理是计算机绘图中一个引人注目的问题, 目前已提出多种算法, 基本上可以分为两大类:即物体空间方法和图象空间方法。
物体空间方法是通过比较物体和物体的相对关系来决定可见与不可见的;而图象空间方法则是根据在图象象素点上各投影点之间的关系来确定可见与否的。
用这两类方法就可以消除凸型模型、凹形模型和多个模型同时存在时的隐藏面。
1).消隐算法的实现1.物体空间的消隐算法物体空间法是在三维坐标系中, 通过分析物体模型间的几何关系, 如物体的几何位置、与观察点的相对位置等, 来进行隐藏面判断的消隐算法。
世界坐标系是描述物体的原始坐标系, 物体的世界坐标描述了物体的基本形状。
为了更好地观察和描述物体, 经常需要对其世界坐标进行平移和旋转, 而得到物体的观察坐标。
物体的观察坐标能得到描述物体的更好视角, 所以物体空间法通常都是在观察坐标系中进行的。
观察坐标系的原点一般即是观察点。
物体空间法消隐包括两个基本步骤, 即三维坐标变换和选取适当的隐藏面判断算法。
选择合适的观察坐标系不但可以更好地描述物体, 而且可以大大简化和降低消隐算法的运算。
因此, 利用物体空间法进行消隐的第一步往往是将物体所处的坐标系转换为适当的观察坐标系。
这需要对物体进行三维旋转和平移变换。
常用的物体空间消隐算法包括平面公式法、径向预排序法、径向排序法、隔离平面法、深度排序法、光线投射法和区域子分法。
计算机图形学大作业报告记录(灯光纹理映射)
计算机图形学大作业报告记录(灯光纹理映射)————————————————————————————————作者:————————————————————————————————日期:大作业报告实验课程名称:计算机图形学学生姓名:班级:学院(系):学生学号:指导教师:成绩:一、目的这次大作业是作为这学期的最后的一个考核,所以必须要用到所有的本学期学过的知识,比如怎样画出三维图形,怎样在图像上在图像上添加纹理光照,怎样使用鼠标和键盘进行人机交互等。
二、主要功能模块设计1 矩阵运算模块的设计:功能描述:程序启动后,这部分功能模块会为整个应用程序提供算法支持,具体是矩阵直接的相互运算,在2D向3D转化过程中会起到很重要的作用。
代码设计:float vv(float * v1, float * v2){return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];}void vxv(float * n, float * v1, float * v2){n[0] = v1[1] * v2[2] - v1[2] * v2[1];n[1] = v1[2] * v2[0] - v1[0] * v2[2];n[2] = v1[0] * v2[1] - v1[1] * v2[0];}void loadIdentity(Matrix m){Matrix identity = {{1.0,0.0,0.0,0.0},{0.0,1.0,0.0,0.0},{0.0,0.0,1.0,0.0},{0.0,0.0,0.0,1.0}};for(int i = 0;i < 4; i++)for(int j = 0;j < 4; j++)m[i][j] = identity[i][j];}void preMultiply(Matrix p, Matrix m){int i , j;Matrix t;for( i = 0; i < 4; i ++)for( j = 0; j < 4; j++)t[i][j] = p[i][0] * m[0][j] + p[i][1] * m[1][j] + p[i][2] * m[2][j] + p[i][3] * m[3][j];for( i = 0; i < 4; i ++)for( j = 0; j < 4; j ++)m[i][j] = t[i][j];}2 显示图形模块的设计:功能描述:该模块主要为所要画的图形进行描述,是绘制图形的主要函数,通过调用这个功能模块就能画出用于显示给用户的图形。
图形学光照模型课程设计
图形学光照模型课程设计一、教学目标本课程的教学目标是让学生掌握图形学中的光照模型原理,培养学生运用光照模型解决实际问题的能力。
具体目标如下:1.知识目标:–了解光照模型的发展历程和基本原理。
–掌握局部光照模型和全局光照模型的区别与联系。
–熟悉常见光照模型的算法和应用场景。
2.技能目标:–能够运用光照模型对简单几何物体进行渲染。
–能够根据场景需求选择合适的光照模型进行渲染。
–能够通过调整光照参数优化渲染效果。
3.情感态度价值观目标:–培养学生对图形学的兴趣和好奇心,激发学生深入学习光照模型的动力。
–培养学生团队合作意识,鼓励学生在课堂上进行交流与合作。
–培养学生关注现实生活中的图形学应用,提高学生的实践能力。
二、教学内容根据教学目标,本课程的教学内容主要包括以下几个方面:1.光照模型概述:介绍光照模型的定义、发展历程和基本原理。
2.局部光照模型:主要包括朗伯反射模型、金属反射模型和菲涅尔反射模型等,通过实例让学生了解各种模型的特点和应用场景。
3.全局光照模型:主要包括辐射度模型和基于图像的渲染技术,让学生了解全局光照模型的基本原理和实现方法。
4.光照参数调整:教授学生如何根据场景需求调整光照参数,以达到优化渲染效果的目的。
5.实际应用案例:分析现实生活中光照模型的应用实例,让学生了解光照模型在实际中的应用价值。
三、教学方法为了提高教学效果,本课程将采用多种教学方法相结合的方式进行授课:1.讲授法:用于讲解光照模型的基本原理、算法和应用场景。
2.案例分析法:通过分析实际应用案例,让学生更好地理解光照模型在实际中的应用。
3.实验法:安排实验课程,让学生亲自动手实践,掌握光照模型的应用技巧。
4.小组讨论法:鼓励学生在课堂上进行交流与合作,培养学生的团队合作意识。
四、教学资源为了支持教学内容和教学方法的实施,本课程将采用以下教学资源:1.教材:《图形学光照模型》教材,为学生提供系统的理论知识。
2.参考书:推荐学生阅读相关领域的经典著作,拓展学生的知识面。
opengl光照模型实现课程设计
opengl光照模型实现课程设计一、课程目标知识目标:1. 让学生掌握OpenGL中光照模型的基本概念和原理,包括环境光、散射光、镜面光等;2. 使学生了解并掌握OpenGL中实现光照效果的常用函数和技巧;3. 让学生掌握如何使用光照模型为三维场景添加真实感。
技能目标:1. 培养学生运用OpenGL库进行三维场景光照编程的能力;2. 培养学生通过调整光照参数,优化场景光照效果的能力;3. 培养学生运用光照模型解决实际场景渲染问题的能力。
情感态度价值观目标:1. 培养学生对计算机图形学及三维渲染技术的兴趣和热情;2. 培养学生具备团队协作精神,学会在项目实践中互相交流、分享经验;3. 培养学生关注科技发展,了解计算机图形学在现实生活和产业中的应用。
课程性质分析:本课程为计算机图形学相关课程,旨在让学生掌握OpenGL光照模型的应用,提高三维场景渲染的真实感。
学生特点分析:学生具备一定的编程基础和图形学知识,对OpenGL有一定了解,但对光照模型的应用尚不熟悉。
教学要求:1. 理论与实践相结合,注重学生动手实践能力的培养;2. 结合实际案例,引导学生运用所学知识解决实际问题;3. 注重培养学生的团队协作和沟通能力。
二、教学内容1. 光照模型基本原理:包括环境光、散射光、镜面光的产生和计算方法,以及光照模型的组成要素。
- 教材章节:第三章“光照模型基础”2. OpenGL光照函数:介绍OpenGL中实现光照效果的相关函数,如glEnable(GL_LIGHTING)、glLightfv等。
- 教材章节:第四章“OpenGL光照函数”3. 光照参数设置:讲解如何设置光照参数,包括光源位置、颜色、强度等,以及材质属性。
- 教材章节:第五章“光照参数设置”4. 光照效果优化:分析如何通过调整光照参数,优化三维场景的光照效果,提高真实感。
- 教材章节:第六章“光照效果优化”5. 实践案例:结合实际项目,运用光照模型为三维场景添加光照效果,培养学生的实际操作能力。
计算机图形学实验报告-实验5Phong光照模型
计算机图形学实验报告班级计算机工硕班学号 **********姓名王泽晶实验五: Phong光照模型实验目的通过本次试验,学生可以掌握简单光照明模型的计算,以及真实感绘制中三维场景搭建的初步知识。
实验内容:对给定的光源、相机状态,对球进行Phong光照明模型绘制。
搭建三维场景:a)在三维空间中摆放1个球,半径为R,默认为50 ,摆放位置为(0,0,0)b)球的材质默认值为Ka = (0.1,0.1,0.1), Kd = (0,0,0.8), Ks = 0.2, n = 10c)视点方向初始为(0,0,1),光源方向初始为(1,1,1)d)视口设置为x0 = -100, y0 = -75, w = 200, h = 150使用phong模型绘制场景试验步骤:添加成员函数,编写成员数代码为override public function computeIntersection( viewStart:Vec3, viewDir:Vec3):Boolean {// See /geometry/sphereline/var viewEnd:Vec3 = viewStart.add(viewDir);var A:Number = Math.pow(viewEnd.getVec(0) - viewStart.getVec(0), 2)+Math.pow(viewEnd.getVec(1) - viewStart.getVec(1), 2) +Math.pow(viewEnd.getVec(2) - viewStart.getVec(2), 2);var B:Number =((viewEnd.getVec(0) - viewStart.getVec(0)) * (viewStart.getVec(0) - _position.getVec(0)) +(viewEnd.getVec(1) - viewStart.getVec(1)) * (viewStart.getVec(1) -_position.getVec(1)) +(viewEnd.getVec(2) - viewStart.getVec(2)) * (viewStart.getVec(2) -_position.getVec(2))) * 2.0;var C:Number = Math.pow(_position.getVec(0) - viewStart.getVec(0), 2) + Math.pow(_position.getVec(1) - viewStart.getVec(1), 2) +Math.pow(_position.getVec(2) - viewStart.getVec(2), 2) - _radius*_radius;// Solve C + Bt + At^2 = 0var delta:Number = B*B - 4*A*C;if ( delta<0.0 || A==0.0 ) return false;// We don't consider whether 0<t<1 here because real viewer is at infinite place var t1:Number = (-B + Math.sqrt(delta)) / (2*A);var t2:Number = (-B - Math.sqrt(delta)) / (2*A);if ( t1<t2 )point = viewStart.multiplyk(1.0 - t1).add(viewEnd.multiplyk(t1));elsepoint = viewStart.multiplyk(1.0 - t2).add(viewEnd.multiplyk(t2));normal = Vec3.normalize(point.minus(_position));return true;}public var _width :Number =0.0;public var _height:Number = 0.0;public var data:Array = new Array();protected function group1_creationCompleteHandler(event:FlexEvent):void{draw();}public function draw():void{graphics.clear();if(txtViewDir.text == "")return;var ary:Array = txtViewDir.text.split(",");var flag:Boolean = false;for(var i:int= 0;i<ary.length;i++){if(ary[i] == "" || isNaN(ary[i])){flag = true;break;}}if(flag)txtViewDir.setStyle("color",0xff0000);return;}txtViewDir.setStyle("color",0x000000);var viewDir:Vec3 = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));ary = txtLight.text.split(",");flag = false;for(i= 0;i<ary.length;i++){if(ary[i] == "" || isNaN(ary[i])){flag = true;break;}}if(flag){txtLight.setStyle("color",0xff0000);return;}txtLight.setStyle("color",0x000000);var light:Light = new Light();light.direction = new Vec3(Number(ary[0]), Number(ary[1]),Number(ary[2])).negative();light.ambient = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));light.intensity = new Vec3(Number(ary[0]), Number(ary[1]), Number(ary[2]));var material:Material = new Material();material.diffuse =new Vec3(0.0, 0.0, 0.8);material.specular =new Vec3(0.2, 0.2, 0.2);material.ambient =new Vec3(0.1, 0.1, 0.1);data = createSceneImage( 200, 150, viewDir, light, material );drawImg();}public function drawImg():void{for(var y:int = 0 ;y<150;y++)for(var x:int =0;x<200;x++){var index:int = (y*200 + x) * 3;var r:Number = data[index+0];var g:Number = data[index+1];var b:Number = data[index+2];var cl:uint =(r << 16) | (g << 8) | b;this.graphics.beginFill(cl)this.graphics.drawCircle(x,y,1);this.graphics.endFill();}}}public function allocateBuffer( width:int,height: int ):Array{var data:Array = new Array();data.length = width * height * 3;_width = width;_height = heightreturn data;}public function createSceneImage( width:int,height: int ,viewDir:Vec3, light:Light, material:Material ):Array{var data:Array = new Array();var sphere:SphereObject = new SphereObject(50.0);sphere.setPosition(new Vec3(0.0, 0.0, 0.0) );sphere.setMaterial( material );var halfW:int = width / 2var halfH:int = height / 2;for ( var y:int=0; y<height; ++y ){for ( var x:int=0; x<width; ++x ){var viewStart:Vec3 = new Vec3(Number(x - halfW), Number(y - halfH), 0.0);if ( puteIntersection(viewStart, viewDir) )sphere.color = puteColor(light, viewDir, sphere.normal);elsesphere.color = new Vec3(0.1, 0.1, 0.1);var index:int = (y*width + x) * 3;data[index+0] = (sphere.color.getVec(0) * 255.0);data[index+1] = (sphere.color.getVec(1) * 255.0);data[index+2] = (sphere.color.getVec(2) * 255.0);}}return data;}protected function button1_clickHandler(event:MouseEvent):void {// TODO Auto-generated method stubdraw();}编译运行得到如下结果:。
计算机图形学实验报告
实验结果与结论
• 在本次实验中,我们成功地实现了复杂场景的渲染,得到了具有较高真实感和视觉效果的图像。通过对比 实验前后的效果,我们发现光线追踪和着色器的运用对于提高渲染质量和效率具有重要作用。同时,我们 也发现场景图的构建和渲染脚本的编写对于实现复杂场景的渲染至关重要。此次实验不仅提高了我们对计 算机图形学原理的理解和实践能力,也为我们后续深入研究渲染引擎的实现提供了宝贵经验。
2. 通过属性设置和变换操作,实现了对图形的定 制和调整,加深了对图形属性的理解。
4. 实验的不足之处:由于时间限制,实验只涉及 了基本图形的绘制和变换,未涉及更复杂的图形 处理算法和技术,如光照、纹理映射等。需要在 后续实验中进一步学习和探索。
02
实验二:实现动画效果
实验目的
掌握动画的基本原 理和实现方法
04
实验四:渲染复杂场景
实验目的
掌握渲染复杂场景的基本流程和方法 理解光线追踪和着色器在渲染过程中的作用
熟悉渲染引擎的实现原理和技巧 提高解决实际问题的能力
实验步骤
• 准备场景文件 • 使用3D建模软件(如Blender)创建或导入场景模型,导出为常用的3D格式(如.obj或.fbx)。 • 导入场景文件 • 在渲染引擎(如Unity或Unreal Engine)中导入准备好的场景文件。 • 构建场景图 • 根据场景的层次结构和光照需求,构建场景图(Scene Graph)。 • 设置光照和材质属性 • 为场景中的物体设置光照和材质属性(如漫反射、镜面反射、透明度等)。 • 编写渲染脚本 • 使用编程语言(如C或JavaScript)编写渲染脚本,控制场景中物体的渲染顺序和逻辑。 • 运行渲染程序 • 运行渲染程序,观察渲染结果。根据效果调整光照、材质和渲染逻辑。 • 导出渲染图像 • 将渲染结果导出为图像文件(如JPEG或PNG),进行后续分析和展示。
计算机图形学课程设计报告1
目录1、课程设计目的 (1)2、系统功能介绍 (1)3、程序代码和分析 (2)4、总结 (4)5、参考文献 (4)6.源程序 (4)计算机图形学课程设计报告1.课程设计目的本课程主要内容包括计算机图形学的研究内容、发展与应用,图形输入输出设备,图形显示原理,图形软件标准,基本图形生成算法,图形几何变换与裁剪,自由曲线和曲面,三维实体造型,分形几何造型,分形艺术,隐藏面消除,光照模型,颜色模型,光线跟踪,纹理细节模拟,常用的计算机动画技术和软件等。
在学期期末时按课程要求进行运动,提高学生对计算机图形学知识的了解与运用技巧同时通过此次课程设计提高动手实践能力与学习分析能力这就是本次的课程设计的目的。
2.课程设计描述及要求此次课程设计的课题为利用VC++6.0和插件OPENGL制作三维模型。
本设计主要通过建立MFC工程,在工程里建立一个三维模型然后再进行旋转,飞行等运动,来建立一个动态的三维模型。
主要步骤如下:1:工程的建立2:三维模型的建立和映射3:三维模型的运动一:工程的建立1:系统配置。
先对机子安装VC++6.0.在建立工程前,本实验需要添加OPENGL 插件,故需要在Windows环境下安装GLUT步骤如下:1、将下载的压缩包解开,将得到5个文件2、在“我的电脑”中搜索“gl.h”,并找到其所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\PlatformSDK\include\gl文件夹”)。
把解压得到的glut.h放到这个文件夹。
3、把解压得到的glut.lib和glut32.lib放到静态函数库所在文件夹(如果是VisualStudio2005,则应该是其安装目录下面的“VC\lib”文件夹)。
4、把解压得到的glut.dll和glut32.dll放到操作系统目录下面的system32文件夹内。
(典型的位置为:C:\Windows\System32)然后建立一个OpenGL工程测试这里以VisualStudio2005为例。
计算机图形学课程设计报告报告
一、设计容与要求1.1、设计题目算法实现时钟运动1.2、总体目标和要求(1)目标:以图形学算法为目标,深入研究。
继而策划、设计并实现一个能够表现计算机图形学算法原理的或完整过程的演示系统,并能从某些方面作出评价和改进意见。
通过完成一个完整程序,经历策划、设计、开发、测试、总结和验收各阶段,达到巩固和实践计算机图形学课程中的理论和算法;学习表现计算机图形学算法的技巧;培养认真学习、积极探索的精神。
(2)总体要求:策划、设计并实现一个能够充分表现图形学算法的演示系统,界面要求美观大方,能清楚地演示算法执行的每一个步骤。
(3)开发环境:Viusal C++ 6.01.3、设计要求容:(1)掌握动画基本原理;(2)实现平面几何变换;功能要求:(1)显示时钟三个时针,实现三根时针间的相互关系;(2)通过右键菜单切换时钟背景与时针颜色;1.4设计方案通过使用OpenGL提供的标准库函数,综合图形学Bresenham 画线和画圆的算法,OpenGL颜色模型中颜色表示模式等实现指针式时钟运动,并通过点击右键菜单实习时钟背景与时针颜色的转换。
根据Bresenham画线和画圆的算法,画出时钟的指针和表盘。
再根据OpenGL颜色模型定义当前颜色。
设置当时钟运行时交换的菜单,运行程序时可变换时钟背景与时针的颜色。
最后再设置一个恢复菜单恢复开始时表盘与指针的颜色。
二、总体设计2.1、过程流程图2.2、椭圆的中点生成算法1、椭圆对称性质原理:(1)圆是满足x 轴对称的,这样只需要计算原来的1/2点的位置;(2)圆是满足y 轴对称的,这样只需要计算原来的1/2点的位置;通过上面分析可以得到实际上我们计算椭圆生成时候,只需要计算1/4个椭圆就可以实现对于所有点的生成了。
2、中点椭圆算法容:(1)输入椭圆的两个半径r1和r2,并且输入椭圆的圆心。
设置初始点(x0,y0)的位置为(0,r2);(2)计算区域1中央决策参数的初始值p = ry*ry - rx*rx*ry + 1/4*(rx*rx);(3)在区域1中的每个Xn为止,从n = 0 开始,直到|K|(斜率)小于-1时后结束;<1>如果p < 0 ,绘制下一个点(x+1,y),并且计算p = p + r2*r2*(3+2*x);<2>如果P >=0 ,绘制下一个点(x+1,y-1),并且计算p = p + r2*r2*(3+2*point.x) - 2*r1*r1*(y-1)(4)设置新的参数初始值;p = ry*ry(X0+1/2)*(X0+1/2) + rx*rx*(Y0-1) - rx*rx*ry*ry; (5)在区域2中的每个Yn为止,从n = 0开始,直到y = 0时结束。
计算机图形学第十章课程大纲
10.2 简单光照模型
简单光照模型表示为
物体表面任意一点的光反射强度是环境光反射强度I e 、光源漫反射强度I d 、光源镜面反射强度I s 之和。
光反射强度:光通量,单位是流明
10.2.1 材质模型
不同材质对不同类型光的反射系数。
10.2.2 环境光模型
由周围物体多次反射所产生的环境光来自周围各个方向,又均匀地向各个方向反射。
特点:
与视点无关,与物体表面位置无关
10.2.3 漫反射光模型
漫反射光是从一点照射,均匀地向各个方向散射,因此漫反射光与视点无关。
s d I I ++=e I I
特点:
与视点无关,与表面位置有关
10.2.4 镜面反射光模型
镜面反射光是只朝一个方向反射的光,具有很强的方向性,并遵守反射定律 。
镜面反射光会在光滑物体表面形成一片非常亮的区域,称为高光(highlight )区域。
特点:
与视点有关,与表面位置有关
简单光照模型
n p
s p d a a s d e N H I k N L I k I k I I I I )0,max()0,max(⋅+⋅+=++=
10.3 光滑着色
10.3.1 直线段的光滑着色
c=(1−t)c0+tc1
10.3.2 Gouraud明暗处理
Gouraud双线性光强插值模型;
通过有效边多边形填充算法实现插值填充,先在y方向插值,后在x方向插值;
I d=(1−t)I A+tI c
10.3.3 Phong明暗处理
Phong双线性法矢插值模型;
总结
简单光照模型
Phong明暗处理和Gouraud明暗处理。
球体Phong光照模型课程设计报告
计算机图形学课程设计课程设计球体Phong光照模型一、实验目的(1)掌握双线性法矢插值模型;(2)掌握ZBuffer算法的思想;(3)掌握有效边表填充算法;二、实验要求1、建立三维坐标系Oxyz,原点位于屏幕客户区中心,x轴水平向右为正,y轴垂直向上为正,z轴垂直于屏幕指向观察者。
2、绘制体心和坐标系中心重合的球体表面,使用Z-Buffer消隐算法进行消隐。
3、使用单点光源对球体进行照射生成Phong光照模型,光源位置位于球体右上方。
4、背景色设置为RGB(128,0,0)。
5、使用键盘方向键旋转球体。
6、使用鼠标左击缩小球体、右击增大球体。
三、实验步骤建立球体的网格模型,使用地理划分法将球体北极和南极划分为三角形面片,其余部分划分为四边形面片,先对球体网格模型进行背面剔除,然后使用深度缓冲算法进行消隐。
计算面片各顶点的平均法矢量,然后采用双线性法失插值计算面片内各点的法矢量。
最终根据每点的法矢量对光源的朝向,通过简单光照模型计算所获得的光强。
面片使用有效边表算法填1、Phong双线性法矢插值模型Gouraud双线性光强插值模型解决了相邻多边形之间的颜色突变问题,产生的真实感图形颜色过渡均匀,图形显得非常光滑,这是它的优点,但是,由于采用光强插值,其镜面反射光效果不太理想,而且相邻多边形边界处的马赫带效应并不能完全消除。
Phong 模型提出的双线性法矢插值模型可以有效的解决上述问题,产生正确的高光区域。
Phong 模型在进行光强插值的时候,需要先对面片的每一个顶点计算平均法矢量,然后通过双线性法矢插值计算面片内每个点的法矢量,最后根据简单光照模型计算面片上各点的颜色值。
基本算法如下。
(1)计算面片顶点的平均法矢量。
∑∑===ni ini iNN N 11由于球心位于三维坐标系原点,所以球面上任意面片的顶点平均法矢量就是该点的位置矢量。
(2)计算面片内部各点的法矢量。
在图中,三角形面片的顶点坐标为),(000y x P ,法矢量为0N ;),,(111y x P 法矢量是1N ;。
计算机图形学实验报告
计算机图形学实验报告计算机图形学实验报告引言计算机图形学是研究计算机生成和处理图像的学科,它在现代科技和娱乐产业中扮演着重要的角色。
本实验报告旨在总结和分享我在计算机图形学实验中的经验和收获。
一、实验背景计算机图形学实验是计算机科学与技术专业的一门重要课程,通过实践操作和编程,学生可以深入了解图形学的基本原理和算法。
本次实验主要涉及三维图形的建模、渲染和动画。
二、实验内容1. 三维图形建模在实验中,我们学习了三维图形的表示和建模方法。
通过使用OpenGL或其他图形库,我们可以创建基本的几何体,如立方体、球体和圆柱体,并进行变换操作,如平移、旋转和缩放。
这些基本操作为后续的图形处理和渲染打下了基础。
2. 光照和着色光照和着色是图形学中重要的概念。
我们学习了不同的光照模型,如环境光、漫反射和镜面反射,并了解了如何在三维场景中模拟光照效果。
通过设置材质属性和光源参数,我们可以实现逼真的光照效果,使物体看起来更加真实。
3. 纹理映射纹理映射是一种将二维图像映射到三维物体表面的技术。
通过将纹理图像与物体的顶点坐标相对应,我们可以实现更加细致的渲染效果。
在实验中,我们学习了纹理坐标的计算和纹理映射的应用,使物体表面呈现出具有纹理和细节的效果。
4. 动画和交互动画和交互是计算机图形学的重要应用领域。
在实验中,我们学习了基本的动画原理和算法,如关键帧动画和插值技术。
通过设置动画参数和交互控制,我们可以实现物体的平滑移动和变形效果,提升用户体验。
三、实验过程在实验过程中,我们首先熟悉了图形库的使用和基本的编程技巧。
然后,我们按照实验指导书的要求,逐步完成了三维图形建模、光照和着色、纹理映射以及动画和交互等任务。
在实验过程中,我们遇到了许多挑战和问题,但通过不断的尝试和调试,最终成功实现了预期的效果。
四、实验结果通过实验,我们成功实现了三维图形的建模、渲染和动画效果。
我们可以通过键盘和鼠标控制物体的移动和变形,同时观察到真实的光照效果和纹理映射效果。
计算机图形学实验报告三
《计算机图形学》实验报告glClear(GL_COLOR_BUFFER_BIT);//glEnable(GL_SCISSOR_TEST);//glScissor(0.0f,0.0f,500,300);glutWireTeapot(0.4);glFlush();}//窗口调整子程序void myReshape(int w, int h){glViewport(500, -300, (GLsizei)w, (GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho(-1, 1, -(float)h / w, (float)h / w, -1, 1);elseglOrtho(-(float)w / h, (float)w / h, -1, 1, -1, 0.5);}2,使用opengl函数写一个图形程序,要求分别使用三个光源从一个茶壶的前右上方(偏红色),正左侧(偏绿色)和前左下方(偏蓝色)对于其进行照射,完成程序并观察效果。
}//绘图子程序void display(void){glColor3f(1.0, 1.0, 0.0);glClear(GL_COLOR_BUFFER_BIT);//glMatrixMode(GL_MODELVIEW);//glLoadIdentity();//设置光源的属性1GLfloat LightAmbient1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; //环境光参数 ( 新增 )GLfloat LightDiffuse1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; // 漫射光参数 ( 新增 )GLfloat Lightspecular1[] = { 1.0f, 0.0f, 0.0f, 1.0f }; // 镜面反射GLfloat LightPosition1[] = { 500.0f, 500.0f, 500.0f, 1.0f }; // 光源位置 ( 新增 ) glLightfv(GL_LIGHT0, GL_POSITION, LightPosition1);glViewport(0, 0, (GLsizei)w, (GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();3,使用opengl函数完成一个图形动画程序,显示一个球沿正弦曲线运动的过程,同时显示一个立方体沿抛物线运动过程。
计算机图形学课程设计报告 简单光照
目录目录 (I)一、选题背景....................................................... 错误!未定义书签。
1.1 内容要求 ................................................. 错误!未定义书签。
1.1.1 内容设计 (2)1.1.2 基本要求 (2)二、算法设计....................................................... 错误!未定义书签。
2.1 相关原理 ................................................. 错误!未定义书签。
2.1.1 明暗模型 (3)2.1.2 镜面反射与Phong模型 (3)2.1.3 渲染 (3)2.2 模块划分 (4)三、程序及功能说明 (2)3.1 光照类型选择模块 (4)3.2 材质选择模块 (6)3.3 光照位置选择模块 (8)四、结果分析 (11)4.1 运行截图...... .. (11)五、总结........................................................... 错误!未定义书签。
六、课程设计心得体会....................................... 错误!未定义书签。
参考文献............................................................... 错误!未定义书签。
源程序. (18)三、程序及功能说明3.1 光照类型选择模块1、漫反射光代码if(Chk2){if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}2、环境光代码if(Chk1){ if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,N dr);dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;3、镜面反射光代码if(Chk3){double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,N dr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}3.2 材质选择模块1、金材质代码void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}2、银材质代码void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}3、红宝石材质代码void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}4、绿宝石材质代码void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}3.2 光照位置选择模块1、上右位置代码void CTestView::OnCheck11(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk11){Positionx=300;Positiony=300;Positionz=-300;Chk11=!Chk11;}else{Chk11=!Chk11;}Invalidate(false);UpdateData(false);}2、下右位置代码void CTestView::OnCheck12(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk12){Positionx=300;Positiony=300;Positionz=300;Chk12=!Chk12;}else{Chk12=!Chk12;}Invalidate(false);UpdateData(false);}3、上左位置代码void CTestView::OnCheck9(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk9){Positionx=-300;Positiony=300;Positionz=-300;Chk9=!Chk9;}else{Chk9=!Chk9;}Invalidate(false);UpdateData(false);}4、下左位置代码void CTestView::OnCheck10(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk10){Positionx=-300;Positiony=300;Positionz=300;Chk10=!Chk10;}else{Chk10=!Chk10;}Invalidate(false);UpdateData(false);}四、结果分析4.1 运行截图图4-1 左上角光照显示结果图4-2 右下角光照显示结果图4-3 右上角光照显示结果图4-4 左下角源程序#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#include "math.h"//数学头文件#define ROUND(a) int(a+0.5)//四舍五入#define PI 3.1415926//圆周率#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView)ON_WM_ERASEBKGND()ON_COMMAND(IDR_Light, OnLight)ON_BN_CLICKED(IDC_CHECK1, OnCheck1)ON_BN_CLICKED(IDC_CHECK2, OnCheck2)ON_BN_CLICKED(IDC_CHECK3, OnCheck3)ON_BN_CLICKED(IDC_CHECK4, OnCheck4)ON_BN_CLICKED(IDC_CHECK5, OnCheck5)ON_BN_CLICKED(IDC_CHECK6, OnCheck6)ON_BN_CLICKED(IDC_CHECK7, OnCheck7)ON_BN_CLICKED(IDC_CHECK8, OnCheck8)ON_BN_CLICKED(IDC_CHECK9, OnCheck9)ON_BN_CLICKED(IDC_CHECK10, OnCheck10) ON_BN_CLICKED(IDC_CHECK11, OnCheck11) ON_BN_CLICKED(IDC_CHECK12, OnCheck12) //}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code hereChk1=Chk2=Chk3=Chk4=Chk5=Chk6=false;Chk7=Chk8=Chk9=Chk10=Chk11=Chk12=false;r=100;//球半径R=300;Fei=90;Thta=90;D=800;//视点参数LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;n=5;//高光指数}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereAfxGetMainWnd()->SetWindowText("光照模型:光源");GetMaxX();GetMaxY();InitParameter();ReadPoint();ReadFace();DrawGlobe();}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::GetMaxX()//获得屏幕宽度{CRect Rect;GetClientRect(&Rect);MaxX=Rect.right;}void CTestView::GetMaxY()//获得屏幕高度{CRect Rect;GetClientRect(&Rect);MaxY=Rect.bottom;}void CTestView::ReadPoint()//读入点坐标{double afa,beta;for(int i=0;i<37;i++){afa=i*5*PI/180;for(int j=0;j<72;j++){beta=j*5*PI/180;P[i][j].x=r*sin(afa)*cos(beta);P[i][j].y=r*sin(afa)*sin(beta);P[i][j].z=r*cos(afa);}}}void CTestView::ReadFace()//读入面坐标{for(int i=0;i<36;i++){for(int j=0;j<72;j++){F[i][j].p[0]=P[i][j];F[i][j].p[1]=P[i+1][j];if(j==71){F[i][j].p[2]=P[i+1][0];F[i][j].p[3]=P[i][0];}else{F[i][j].p[2]=P[i+1][j+1];F[i][j].p[3]=P[i][j+1];}}}}void CTestView::DrawGlobe(){CRect Rect;GetClientRect(&Rect);CDC MemDC;CBitmap Bitmap,*OldBitmap;Bitmap.LoadBitmap(IDB_BITMAP2);MemDC.CreateCompatibleDC(GetDC());OldBitmap=MemDC.SelectObject(&Bitmap);MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);for(int i=0;i<36;i++){for(int j=0;j<72;j++){for(int m=0;m<4;m++){P1[m].x=F[i][j].p[m].x;P1[m].y=F[i][j].p[m].y;P1[m].z=F[i][j].p[m].z;Pdown[m].x=F[i+1][j].p[m].x;Pdown[m].y=F[i+1][j].p[m].y;Pdown[m].z=F[i+1][j].p[m].z;if(j==71){Pright[m].x=F[i][0].p[m].x;Pright[m].y=F[i][0].p[m].y;Pright[m].z=F[i][0].p[m].z;Pdownright[m].x=F[i+1][0].p[m].x;Pdownright[m].y=F[i+1][0].p[m].y;Pdownright[m].z=F[i+1][0].p[m].z;}else{Pright[m].x=F[i][j+1].p[m].x;Pright[m].y=F[i][j+1].p[m].y;Pright[m].z=F[i][j+1].p[m].z;Pdownright[m].x=F[i+1][j+1].p[m].x;Pdownright[m].y=F[i+1][j+1].p[m].y;Pdownright[m].z=F[i+1][j+1].p[m].z;}}bool First=true;P3d Pt[3];//四边形划分为两个三角形面片Pt[0]=P1[0];Pt[1]=P1[1];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制上三角形面片First=false;Pt[0]=P1[1];Pt[1]=P1[2];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制下三角形面片First=true;}}CClientDC dc(this);dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);MemDC.SelectObject(OldBitmap);}void CTestView::Triangle(CDC *mdc,P3d *p,bool First)//三角形面片{Vector vP10(P1[0]),vP11(P1[1]),vP12(P1[2]);//三角形平面片点矢量Vector vPd0(Pdown[0]),vPd1(Pdown[1]),vPd2(Pdown[2]);Vector vPr0(Pright[0]),vPr1(Pright[1]),vPr2(Pright[2]);Vector vPdr0(Pdownright[0]),vPdr1(Pdownright[1]),vPdr2(Pdownright[2]);Vector VectorN1=NormalVector(vP10,vP11,vP12);//主面片法矢量Vector VectorNd=NormalVector(vPd0,vPd1,vPd2);//下面片法矢量Vector VectorNr=NormalVector(vPr0,vPr1,vPr2);//右面片法矢量Vector VectorNdr=NormalVector(vPdr0,vPdr1,vPdr2);//下右面片法矢量Vector N1,Nd,Nr,Ndr;N1=VectorN1.Unit();Nd=VectorNd.Unit();Nr=VectorNr.Unit();Ndr=VectorNdr.Unit();Vector LPosition(lightP.position),Lv=LPosition.Unit();MyRGB Ambientc=lightP.ambient;MyRGB Ambientd=lightP.ambient;MyRGB Ambientdr=lightP.ambient;MyRGB Ambientr=lightP.ambient;Vector vP0(p[0]),Uv;Vector VisualP(R*k[5],R*k[6],R*k[4]);//视点矢量球坐标Vector VisualV=VisualP-vP0;//视矢量Uv=VisualV.Unit();if(Chk1)//环境光{if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,Ndr); dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;if(Chk2)//漫反射光{if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}if(Chk3)//镜面反射光{double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,Ndr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}//*****************有效边表算法开始***********************void CTestView::SphereFill(CDC* mdc)//下闭上开填充{HeadE=NULL;for(CurrentB=HeadB;CurrentB!=NULL;CurrentB=CurrentB->next)//访问所有桶结点{for(CurrentE=CurrentB->p;CurrentE!=NULL;CurrentE=CurrentE->next)//访问桶中排序前的边结点{Edge *TEdge=new Edge;TEdge->k=CurrentE->k;TEdge->x=CurrentE->x;TEdge->yMax=CurrentE->yMax;TEdge->x1=CurrentE->x1;TEdge->y1=CurrentE->y1;TEdge->c1=CurrentE->c1;TEdge->x2=CurrentE->x2;TEdge->y2=CurrentE->y2;TEdge->c2=CurrentE->c2;TEdge->next=NULL;AddAet(TEdge);//将该边插入临时Aet表}AetOrder();//使得Aet表按照x递增的顺序存放T1=HeadE;//根据ymax抛弃扫描完的边结点if(T1==NULL){return;}while(CurrentB->ScanLine>=T1->yMax)//放弃该结点,Aet表指针后移{T1=T1->next;HeadE=T1;if(HeadE==NULL){return;}}if(T1->next!=NULL){T2=T1;T1=T2->next;}while(T1!=NULL){if(CurrentB->ScanLine>=T1->yMax)//跳过一个结点{T2->next=T1->next;T1->next=NULL;T1=T2->next;}else{T2=T1;T1=T2->next;}}MyRGB Is,It,Ip;if(CurrentE!=NULL)//扫描线上两边共线{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->c2,Head E->c1);}else{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->next->c2 ,HeadE->next->c1);}BOOL In=false;//设置一个BOOL变量In,初始值为假int xb,xe;//扫描线区间的起点和终点for(T1=HeadE;T1!=NULL;T1=T1->next)//填充扫描线和多边形相交的区间{if(In==false){xb=ROUND(T1->x)-1;In=true;//每访问一个结点,把In值取反一次}else//如果In值为真,则填充从当前结点的x值开始到下一结点的x值结束的区间{xe=ROUND(T1->x);for(int x=xb;x<=xe;x++){Ip=Interpolation(x,xb,xe,Is,It);mdc->SetPixel(MaxX/2+x,MaxY/2+CurrentB->ScanLine,RGB((BYTE)(Ip.red*255),(BYTE )(Ip.green*255),(BYTE)(Ip.blue*255)));}In=false;}for(T1=HeadE;T1!=NULL;T1=T1->next)//边连贯性{T1->x=T1->x+T1->k;//x=x+1/k}}delete HeadB;delete CurrentB;delete CurrentE;delete HeadE;}MyRGB CTestView::Interpolation(int m,int m1,int m2,MyRGB &c1,MyRGB &c2)//边界插值{MyRGB I;I.red=double(m-m2)/(m1-m2)*c1.red+double(m1-m)/(m1-m2)*c2.red;I.green=double(m-m2)/(m1-m2)*c1.green+double(m1-m)/(m1-m2)*c2.green;I.blue=double(m-m2)/(m1-m2)*c1.blue+double(m1-m)/(m1-m2)*c2.blue;return I;}void CTestView::CreatBucket()//初始化桶结点{int ScanMin,ScanMax;//确定扫描线的最小值和最大值ScanMax=ScanMin=Point[0].y;for(int i=1;i<Number;i++){if(Point[i].y<ScanMin){ScanMin=Point[i].y;//扫描线的最小值}if(Point[i].y>ScanMax){ScanMax=Point[i].y;//扫描线的最大值}for(i=ScanMin;i<=ScanMax;i++)//建立桶结点{if(ScanMin==i){HeadB=new Bucket;//建立桶的头结点CurrentB=HeadB;//CurrentB为Bucket当前结点指针CurrentB->ScanLine=ScanMin;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}else//建立桶的其它结点{CurrentB->next=new Bucket;//新建一个桶结点CurrentB=CurrentB->next;//使CurrentB指向新建的桶结点CurrentB->ScanLine=i;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}}}void CTestView::Et()//构造边表{for(int i=0;i<Number;i++)//访问每个顶点{CurrentB=HeadB;//从桶链表的头结点开始循环int j=i+1;//边的第二个顶点,Point[i]和Point[j]构成边if(j==Number) j=0;//保证多边形的闭合if(Point[j].y>Point[i].y)//边在扫描线的上方{while(CurrentB->ScanLine!=Point[i].y)//在桶内寻找该边的yMin{CurrentB=CurrentB->next;//在桶内寻找该边的yMin}E[i].x=Point[i].x;//计算Aet表的值E[i].yMax=Point[j].y;E[i].k=(Point[j].x-Point[i].x)/(Point[j].y-Point[i].y);//代表1/kE[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;//获得桶上链接边表的地址if(CurrentE==NULL)//当前桶结点上没有链接边结点{CurrentE=&E[i];//赋边的起始地址CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中}else{while(CurrentE->next!=NULL)//如果当前边已连有边结点{CurrentE=CurrentE->next;//移动指针到当前边的最后一个边结点}CurrentE->next=&E[i];//把当前边接上去}}if(Point[j].y<Point[i].y)//边在扫描线的下方{while(CurrentB->ScanLine!=Point[j].y){CurrentB=CurrentB->next;}E[i].x=Point[j].x;E[i].yMax=Point[i].y;E[i].k=(Point[i].x-Point[j].x)/(Point[i].y-Point[j].y);E[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;if(CurrentE==NULL){CurrentE=&E[i];CurrentB->p=CurrentE;}else{while(CurrentE->next!=NULL){CurrentE=CurrentE->next;}CurrentE->next=&E[i];}}}CurrentB=NULL;CurrentE=NULL;}void CTestView::AddAet(Edge *NewEdge)//边插入Aet表{T1=HeadE;if(T1==NULL)//Aet表为空,将Aet表置为TEdge{T1=NewEdge;HeadE=T1;}else{while(T1->next!=NULL)//Aet表不为空,将TEdge连在该边之后{T1=T1->next;}T1->next=NewEdge;}}void CTestView::AetOrder()//对Aet表进行排序{T1=HeadE;if(T1==NULL){return;}if(T1->next==NULL)//如果该Aet表没有再连Aet表{return;//桶结点只有一条边,不需要排序}else{if(T1->next->x<T1->x)//Aet表按x值排序{T2=T1->next;T1->next=T2->next;T2->next=T1;HeadE=T2;}T2=HeadE;T1=HeadE->next;while(T1->next!=NULL)//继续两两比较相连的Aet表的x值,进行排序{if(T1->next->x<T1->x){T2->next=T1->next;T1->next=T1->next->next;T2->next->next=T1;T2=T2->next;}else{T2=T1;T1=T1->next;}}}}BOOL CTestView::OnEraseBkgnd(CDC* pDC)//设置背景色函数{// TODO: Add your message handler code here and/or call defaultCRect Rect;pDC->GetClipBox(&Rect);pDC->FillSolidRect(Rect,RGB(0,0,0));return true;}void CTestView::OnLight(){// TODO: Add your command handler code hereMessageBox("请选择光源!","提示");}void CTestView::OnCheck1()//环境光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk1){ lightP.ambient=LightA*MaterialA;Chk1=!Chk1;}else{Chk1=!Chk1;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck2()//漫反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk2){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.diffuse=LightD*MaterialD;//Lambert公式Chk2=!Chk2;}else{Chk2=!Chk2;}Invalidate(false);UpdateData(false);void CTestView::OnCheck3()//镜面反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk3){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.specular=LightS*MaterialS;//Phong公式Chk3=!Chk3;}else{Chk3=!Chk3;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck8()//星球{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk8){n=4;MaterialA.red=0.2f;MaterialA.green=0.2f;MaterialA.blue=0.2f;MaterialD.red=0.8f;MaterialD.green=0.8f;MaterialD.blue=0.8f;MaterialS.red=1.0f;MaterialS.green=1.0f;MaterialS.blue=1.0f;LightA.red=1.0f;LightA.green=0.0f;LightA.blue=0.0f;。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录目录 (I)一、选题背景....................................................... 错误!未定义书签。
1.1 内容要求 ................................................. 错误!未定义书签。
1.1.1 内容设计 (2)1.1.2 基本要求 (2)二、算法设计....................................................... 错误!未定义书签。
2.1 相关原理 ................................................. 错误!未定义书签。
2.1.1 明暗模型 (3)2.1.2 镜面反射与Phong模型 (3)2.1.3 渲染 (3)2.2 模块划分 (4)三、程序及功能说明 (2)3.1 光照类型选择模块 (4)3.2 材质选择模块 (6)3.3 光照位置选择模块 (8)四、结果分析 (11)4.1 运行截图...... .. (11)五、总结........................................................... 错误!未定义书签。
六、课程设计心得体会....................................... 错误!未定义书签。
参考文献............................................................... 错误!未定义书签。
源程序. (18)三、程序及功能说明3.1 光照类型选择模块1、漫反射光代码if(Chk2){if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}2、环境光代码if(Chk1){ if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,N dr);dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;3、镜面反射光代码if(Chk3){double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,N dr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}3.2 材质选择模块1、金材质代码void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}2、银材质代码void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}3、红宝石材质代码void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}4、绿宝石材质代码void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}3.2 光照位置选择模块1、上右位置代码void CTestView::OnCheck11(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk11){Positionx=300;Positiony=300;Positionz=-300;Chk11=!Chk11;}else{Chk11=!Chk11;}Invalidate(false);UpdateData(false);}2、下右位置代码void CTestView::OnCheck12(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk12){Positionx=300;Positiony=300;Positionz=300;Chk12=!Chk12;}else{Chk12=!Chk12;}Invalidate(false);UpdateData(false);}3、上左位置代码void CTestView::OnCheck9(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk9){Positionx=-300;Positiony=300;Positionz=-300;Chk9=!Chk9;}else{Chk9=!Chk9;}Invalidate(false);UpdateData(false);}4、下左位置代码void CTestView::OnCheck10(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk10){Positionx=-300;Positiony=300;Positionz=300;Chk10=!Chk10;}else{Chk10=!Chk10;}Invalidate(false);UpdateData(false);}四、结果分析4.1 运行截图图4-1 左上角光照显示结果图4-2 右下角光照显示结果图4-3 右上角光照显示结果图4-4 左下角源程序#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#include "math.h"//数学头文件#define ROUND(a) int(a+0.5)//四舍五入#define PI 3.1415926//圆周率#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView)ON_WM_ERASEBKGND()ON_COMMAND(IDR_Light, OnLight)ON_BN_CLICKED(IDC_CHECK1, OnCheck1)ON_BN_CLICKED(IDC_CHECK2, OnCheck2)ON_BN_CLICKED(IDC_CHECK3, OnCheck3)ON_BN_CLICKED(IDC_CHECK4, OnCheck4)ON_BN_CLICKED(IDC_CHECK5, OnCheck5)ON_BN_CLICKED(IDC_CHECK6, OnCheck6)ON_BN_CLICKED(IDC_CHECK7, OnCheck7)ON_BN_CLICKED(IDC_CHECK8, OnCheck8)ON_BN_CLICKED(IDC_CHECK9, OnCheck9)ON_BN_CLICKED(IDC_CHECK10, OnCheck10) ON_BN_CLICKED(IDC_CHECK11, OnCheck11) ON_BN_CLICKED(IDC_CHECK12, OnCheck12) //}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code hereChk1=Chk2=Chk3=Chk4=Chk5=Chk6=false;Chk7=Chk8=Chk9=Chk10=Chk11=Chk12=false;r=100;//球半径R=300;Fei=90;Thta=90;D=800;//视点参数LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;n=5;//高光指数}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereAfxGetMainWnd()->SetWindowText("光照模型:光源");GetMaxX();GetMaxY();InitParameter();ReadPoint();ReadFace();DrawGlobe();}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::GetMaxX()//获得屏幕宽度{CRect Rect;GetClientRect(&Rect);MaxX=Rect.right;}void CTestView::GetMaxY()//获得屏幕高度{CRect Rect;GetClientRect(&Rect);MaxY=Rect.bottom;}void CTestView::ReadPoint()//读入点坐标{double afa,beta;for(int i=0;i<37;i++){afa=i*5*PI/180;for(int j=0;j<72;j++){beta=j*5*PI/180;P[i][j].x=r*sin(afa)*cos(beta);P[i][j].y=r*sin(afa)*sin(beta);P[i][j].z=r*cos(afa);}}}void CTestView::ReadFace()//读入面坐标{for(int i=0;i<36;i++){for(int j=0;j<72;j++){F[i][j].p[0]=P[i][j];F[i][j].p[1]=P[i+1][j];if(j==71){F[i][j].p[2]=P[i+1][0];F[i][j].p[3]=P[i][0];}else{F[i][j].p[2]=P[i+1][j+1];F[i][j].p[3]=P[i][j+1];}}}}void CTestView::DrawGlobe(){CRect Rect;GetClientRect(&Rect);CDC MemDC;CBitmap Bitmap,*OldBitmap;Bitmap.LoadBitmap(IDB_BITMAP2);MemDC.CreateCompatibleDC(GetDC());OldBitmap=MemDC.SelectObject(&Bitmap);MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);for(int i=0;i<36;i++){for(int j=0;j<72;j++){for(int m=0;m<4;m++){P1[m].x=F[i][j].p[m].x;P1[m].y=F[i][j].p[m].y;P1[m].z=F[i][j].p[m].z;Pdown[m].x=F[i+1][j].p[m].x;Pdown[m].y=F[i+1][j].p[m].y;Pdown[m].z=F[i+1][j].p[m].z;if(j==71){Pright[m].x=F[i][0].p[m].x;Pright[m].y=F[i][0].p[m].y;Pright[m].z=F[i][0].p[m].z;Pdownright[m].x=F[i+1][0].p[m].x;Pdownright[m].y=F[i+1][0].p[m].y;Pdownright[m].z=F[i+1][0].p[m].z;}else{Pright[m].x=F[i][j+1].p[m].x;Pright[m].y=F[i][j+1].p[m].y;Pright[m].z=F[i][j+1].p[m].z;Pdownright[m].x=F[i+1][j+1].p[m].x;Pdownright[m].y=F[i+1][j+1].p[m].y;Pdownright[m].z=F[i+1][j+1].p[m].z;}}bool First=true;P3d Pt[3];//四边形划分为两个三角形面片Pt[0]=P1[0];Pt[1]=P1[1];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制上三角形面片First=false;Pt[0]=P1[1];Pt[1]=P1[2];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制下三角形面片First=true;}}CClientDC dc(this);dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);MemDC.SelectObject(OldBitmap);}void CTestView::Triangle(CDC *mdc,P3d *p,bool First)//三角形面片{Vector vP10(P1[0]),vP11(P1[1]),vP12(P1[2]);//三角形平面片点矢量Vector vPd0(Pdown[0]),vPd1(Pdown[1]),vPd2(Pdown[2]);Vector vPr0(Pright[0]),vPr1(Pright[1]),vPr2(Pright[2]);Vector vPdr0(Pdownright[0]),vPdr1(Pdownright[1]),vPdr2(Pdownright[2]);Vector VectorN1=NormalVector(vP10,vP11,vP12);//主面片法矢量Vector VectorNd=NormalVector(vPd0,vPd1,vPd2);//下面片法矢量Vector VectorNr=NormalVector(vPr0,vPr1,vPr2);//右面片法矢量Vector VectorNdr=NormalVector(vPdr0,vPdr1,vPdr2);//下右面片法矢量Vector N1,Nd,Nr,Ndr;N1=VectorN1.Unit();Nd=VectorNd.Unit();Nr=VectorNr.Unit();Ndr=VectorNdr.Unit();Vector LPosition(lightP.position),Lv=LPosition.Unit();MyRGB Ambientc=lightP.ambient;MyRGB Ambientd=lightP.ambient;MyRGB Ambientdr=lightP.ambient;MyRGB Ambientr=lightP.ambient;Vector vP0(p[0]),Uv;Vector VisualP(R*k[5],R*k[6],R*k[4]);//视点矢量球坐标Vector VisualV=VisualP-vP0;//视矢量Uv=VisualV.Unit();if(Chk1)//环境光{if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,Ndr); dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;if(Chk2)//漫反射光{if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}if(Chk3)//镜面反射光{double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,Ndr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}//*****************有效边表算法开始***********************void CTestView::SphereFill(CDC* mdc)//下闭上开填充{HeadE=NULL;for(CurrentB=HeadB;CurrentB!=NULL;CurrentB=CurrentB->next)//访问所有桶结点{for(CurrentE=CurrentB->p;CurrentE!=NULL;CurrentE=CurrentE->next)//访问桶中排序前的边结点{Edge *TEdge=new Edge;TEdge->k=CurrentE->k;TEdge->x=CurrentE->x;TEdge->yMax=CurrentE->yMax;TEdge->x1=CurrentE->x1;TEdge->y1=CurrentE->y1;TEdge->c1=CurrentE->c1;TEdge->x2=CurrentE->x2;TEdge->y2=CurrentE->y2;TEdge->c2=CurrentE->c2;TEdge->next=NULL;AddAet(TEdge);//将该边插入临时Aet表}AetOrder();//使得Aet表按照x递增的顺序存放T1=HeadE;//根据ymax抛弃扫描完的边结点if(T1==NULL){return;}while(CurrentB->ScanLine>=T1->yMax)//放弃该结点,Aet表指针后移{T1=T1->next;HeadE=T1;if(HeadE==NULL){return;}}if(T1->next!=NULL){T2=T1;T1=T2->next;}while(T1!=NULL){if(CurrentB->ScanLine>=T1->yMax)//跳过一个结点{T2->next=T1->next;T1->next=NULL;T1=T2->next;}else{T2=T1;T1=T2->next;}}MyRGB Is,It,Ip;if(CurrentE!=NULL)//扫描线上两边共线{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->c2,Head E->c1);}else{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->next->c2 ,HeadE->next->c1);}BOOL In=false;//设置一个BOOL变量In,初始值为假int xb,xe;//扫描线区间的起点和终点for(T1=HeadE;T1!=NULL;T1=T1->next)//填充扫描线和多边形相交的区间{if(In==false){xb=ROUND(T1->x)-1;In=true;//每访问一个结点,把In值取反一次}else//如果In值为真,则填充从当前结点的x值开始到下一结点的x值结束的区间{xe=ROUND(T1->x);for(int x=xb;x<=xe;x++){Ip=Interpolation(x,xb,xe,Is,It);mdc->SetPixel(MaxX/2+x,MaxY/2+CurrentB->ScanLine,RGB((BYTE)(Ip.red*255),(BYTE )(Ip.green*255),(BYTE)(Ip.blue*255)));}In=false;}for(T1=HeadE;T1!=NULL;T1=T1->next)//边连贯性{T1->x=T1->x+T1->k;//x=x+1/k}}delete HeadB;delete CurrentB;delete CurrentE;delete HeadE;}MyRGB CTestView::Interpolation(int m,int m1,int m2,MyRGB &c1,MyRGB &c2)//边界插值{MyRGB I;I.red=double(m-m2)/(m1-m2)*c1.red+double(m1-m)/(m1-m2)*c2.red;I.green=double(m-m2)/(m1-m2)*c1.green+double(m1-m)/(m1-m2)*c2.green;I.blue=double(m-m2)/(m1-m2)*c1.blue+double(m1-m)/(m1-m2)*c2.blue;return I;}void CTestView::CreatBucket()//初始化桶结点{int ScanMin,ScanMax;//确定扫描线的最小值和最大值ScanMax=ScanMin=Point[0].y;for(int i=1;i<Number;i++){if(Point[i].y<ScanMin){ScanMin=Point[i].y;//扫描线的最小值}if(Point[i].y>ScanMax){ScanMax=Point[i].y;//扫描线的最大值}for(i=ScanMin;i<=ScanMax;i++)//建立桶结点{if(ScanMin==i){HeadB=new Bucket;//建立桶的头结点CurrentB=HeadB;//CurrentB为Bucket当前结点指针CurrentB->ScanLine=ScanMin;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}else//建立桶的其它结点{CurrentB->next=new Bucket;//新建一个桶结点CurrentB=CurrentB->next;//使CurrentB指向新建的桶结点CurrentB->ScanLine=i;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}}}void CTestView::Et()//构造边表{for(int i=0;i<Number;i++)//访问每个顶点{CurrentB=HeadB;//从桶链表的头结点开始循环int j=i+1;//边的第二个顶点,Point[i]和Point[j]构成边if(j==Number) j=0;//保证多边形的闭合if(Point[j].y>Point[i].y)//边在扫描线的上方{while(CurrentB->ScanLine!=Point[i].y)//在桶内寻找该边的yMin{CurrentB=CurrentB->next;//在桶内寻找该边的yMin}E[i].x=Point[i].x;//计算Aet表的值E[i].yMax=Point[j].y;E[i].k=(Point[j].x-Point[i].x)/(Point[j].y-Point[i].y);//代表1/kE[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;//获得桶上链接边表的地址if(CurrentE==NULL)//当前桶结点上没有链接边结点{CurrentE=&E[i];//赋边的起始地址CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中}else{while(CurrentE->next!=NULL)//如果当前边已连有边结点{CurrentE=CurrentE->next;//移动指针到当前边的最后一个边结点}CurrentE->next=&E[i];//把当前边接上去}}if(Point[j].y<Point[i].y)//边在扫描线的下方{while(CurrentB->ScanLine!=Point[j].y){CurrentB=CurrentB->next;}E[i].x=Point[j].x;E[i].yMax=Point[i].y;E[i].k=(Point[i].x-Point[j].x)/(Point[i].y-Point[j].y);E[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;if(CurrentE==NULL){CurrentE=&E[i];CurrentB->p=CurrentE;}else{while(CurrentE->next!=NULL){CurrentE=CurrentE->next;}CurrentE->next=&E[i];}}}CurrentB=NULL;CurrentE=NULL;}void CTestView::AddAet(Edge *NewEdge)//边插入Aet表{T1=HeadE;if(T1==NULL)//Aet表为空,将Aet表置为TEdge{T1=NewEdge;HeadE=T1;}else{while(T1->next!=NULL)//Aet表不为空,将TEdge连在该边之后{T1=T1->next;}T1->next=NewEdge;}}void CTestView::AetOrder()//对Aet表进行排序{T1=HeadE;if(T1==NULL){return;}if(T1->next==NULL)//如果该Aet表没有再连Aet表{return;//桶结点只有一条边,不需要排序}else{if(T1->next->x<T1->x)//Aet表按x值排序{T2=T1->next;T1->next=T2->next;T2->next=T1;HeadE=T2;}T2=HeadE;T1=HeadE->next;while(T1->next!=NULL)//继续两两比较相连的Aet表的x值,进行排序{if(T1->next->x<T1->x){T2->next=T1->next;T1->next=T1->next->next;T2->next->next=T1;T2=T2->next;}else{T2=T1;T1=T1->next;}}}}BOOL CTestView::OnEraseBkgnd(CDC* pDC)//设置背景色函数{// TODO: Add your message handler code here and/or call defaultCRect Rect;pDC->GetClipBox(&Rect);pDC->FillSolidRect(Rect,RGB(0,0,0));return true;}void CTestView::OnLight(){// TODO: Add your command handler code hereMessageBox("请选择光源!","提示");}void CTestView::OnCheck1()//环境光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk1){ lightP.ambient=LightA*MaterialA;Chk1=!Chk1;}else{Chk1=!Chk1;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck2()//漫反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk2){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.diffuse=LightD*MaterialD;//Lambert公式Chk2=!Chk2;}else{Chk2=!Chk2;}Invalidate(false);UpdateData(false);void CTestView::OnCheck3()//镜面反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk3){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.specular=LightS*MaterialS;//Phong公式Chk3=!Chk3;}else{Chk3=!Chk3;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck8()//星球{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk8){n=4;MaterialA.red=0.2f;MaterialA.green=0.2f;MaterialA.blue=0.2f;MaterialD.red=0.8f;MaterialD.green=0.8f;MaterialD.blue=0.8f;MaterialS.red=1.0f;MaterialS.green=1.0f;MaterialS.blue=1.0f;LightA.red=1.0f;LightA.green=0.0f;LightA.blue=0.0f;。