1 / 49

OpenGL 中的颜色、光照和材质

OpenGL 中的颜色、光照和材质. 简单光照 OpenGL 简单光照光源分为:. 简单光照 OpenGL 简单光照光源分为: 辐射光 (Emitted Light) 是最简单的一种光,它直接从物体发出并且不受任何光源影响。 环境光 (Ambient Light) 是由光源发出经环境多次散射而无法确定其方向的光,即似乎来自所有方向。 漫射光 (Diffuse Light) 来自一个方向,它垂直于物体时比倾斜时更明亮。 镜面光 (Specular Light) 来自特定方向并沿另一方向反射出去。. 向场景中加入光照的步骤如下:.

kibo-hicks
Download Presentation

OpenGL 中的颜色、光照和材质

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. OpenGL 中的颜色、光照和材质

  2. 简单光照 OpenGL简单光照光源分为: • 简单光照 OpenGL简单光照光源分为: • 辐射光(Emitted Light)是最简单的一种光,它直接从物体发出并且不受任何光源影响。 • 环境光(Ambient Light)是由光源发出经环境多次散射而无法确定其方向的光,即似乎来自所有方向。 • 漫射光(Diffuse Light)来自一个方向,它垂直于物体时比倾斜时更明亮。 • 镜面光(Specular Light)来自特定方向并沿另一方向反射出去。

  3. 向场景中加入光照的步骤如下: 1. 定义所有物体每个顶点的法向量方向。这些法向量决定了物体表面与光源的相对取向。2. 建立、选择并放置一个或多个光源。3. 建立并选择一个光照模型,它决定了全局环境光照的程度以及视点的有效位置(用于光照计算)。4. 定义场景中物体的材质。

  4. 向场景中加入光照的步骤(函数): 1.为顶点指定法向量:glNormal3fv(n0);glVertex3fv(v0); 不指定就是默认模式。 2.创建光源,指定位置:glLightfv(GL_LIGHT0,GL_POSITION,light_position); glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);注意,GL_POSITION的默认值为(0,0,1,0),它定义了一个指向Z轴负方向的定向光源. 3.选择光照模型:其包括四项内容,即全局环境光强度,观察点靠近场景还是位于无穷远处,对物体的正面和背面是否采用相同的光照计算,以及是否将镜面反射颜色同环境颜色和散射颜色分开,并在纹理操作后应用它.函数有glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER,lmodel_viewer)……,其中近视点还是远视点只影响镜面反射区的计算. 4.启用光照:glEnable(GL_LIGHTING);glEnable(GL_LIGHT0); 5.设置材质属性:用glMaterialfv(GLenum face, GLenum pname, Type* param)函数设置GL_AMBIENT, GL_DIFFUSE, GL_AMBIENT_AND_DIFFUSE, GL_SPECULAR, GL_SHINNESS, GL_EMISSION等值.

  5. 实例:二次曲面物体光照与材质

  6. 步骤1:设置光照 基础知识 • 创建光源 光源有许多特性,如颜色、位置、方向等。 • 设置光源特性参数的函数: • void glLight{if}[v]( GLenum light , GLenum pname , TYPE param ) • 参数light指定所创建的光源号,如 GL_LIGHT0 ,GL_LIGHT1 ,GL_LIGHT2 ... ...参数pname指定光源特性参数param设置相应光源特性值

  7. 步骤1:设置光照:glLightfv • glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); //设置场景的环境光。第一个参数表示是对第0号光源GL_LIGHT0进行设置,第二个参数表示要设置的是环境光成分,第三个参数则是一个数组(表示光照属性值) • glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); //设置在场景照射到粗糙表面时经过漫反射光。第一个参数表示是对第0号光源GL_LIGHT0进行设置,第二个参数表示要设置的是漫反射光成分,第三个参数则是一个数组(表示光照属性值) • glLightfv(GL_LIGHT0,GL_POSITION,light_position); • //设置光源的位置,第三个参数则是一个数组(表示光源的位置值)

  8. 定义光照属性值,分别用数组表示: • float lightAmbient[] = { 0.2f, 0.0f, 0.0f, 1.0f };//定义一个数组,表示整个光照环境,有4个值,分别表示光源中含有红、绿、蓝三种光线的成分 ,第四个参数为透明度值,一般也为1。 • float lightDiffuse[] = { 0.5f, 0.0f, 0.0f, 1.0f };//定义数组,用来表示光源的漫反射. • float lightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };////定义数组,用来表示光源的镜面反射

  9. 光源知识: • 每一个光源都可以设置其属性,这一动作是通过glLight*函数完成的。 • glLight*函数具有三个参数,第一个参数指明是设置哪一个光源的属性,第二个参数指明是设置该光源的哪一个属性,第三个参数则是指明把该属性值设置成多少。 • 光源的属性众多,下面将分别介绍光源的属性。

  10. (1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。 • 这三个属性表示了光源所发出的光的反射特性(以及颜色)。 • 每个属性由四个值表示,分别代表了颜色的R, G, B, A值。 • GL_AMBIENT表示该光源所发出的光,经过非常多次的反射后,最终在整个光照环境中的强度(颜色)。GL_DIFFUSE表示该光源所发出的光,照射到粗糙表面时经过漫反射,所得到的光的强度(颜色)。GL_SPECULAR表示该光源所发出的光,照射到光滑表面时经过镜面反射,所得到的光的强度(颜色)。

  11. (2)GL_POSITION属性。 • 表示光源所在的位置。由四个值(X, Y, Z, W)表示。 • 如果第四个值W为零,则表示该光源位于无限远处,前三个值表示了它所在的方向。这种光源称为方向性光源,通常,太阳可以近似的被认为是方向性光源。 • 如果第四个值W不为零,则X/W, Y/W, Z/W表示了光源的位置。这种光源称为位置性光源。

  12. 光源说明1: • 对于位置性光源,设置其位置与设置多边形顶点的方式相似,各种矩阵变换函数例如:glTranslate*、glRotate*等在这里也同样有效。方向性光源在计算时比位置性光源快了不少,因此,在视觉效果允许的情况下,应该尽可能的使用方向性光源。

  13. 光源说明2: • 在OpenGL中,仅仅支持有限数量的光源。 • 使用GL_LIGHT0表示第0号光源,GL_LIGHT1表示第1号光源,依次类推,OpenGL至少会支持8个光源,即GL_LIGHT0到GL_LIGHT7。

  14. 注:只有 GL_LIGHT0 的 GL_DIFFUSE 和 GL_SPECULAR 的缺省值为 ( 1.0 ,1.0 ,1.0 ,1.0 ) • 其他光源的 GL_DIFFUSE 和 GL_SPECULAR 缺省值均为 ( 0.0 ,0.0 ,0.0 ,1.0 )

  15. 步骤2:设置光照模型:函数glLightModel* • 函数glLightModel*有两个参数,第一个表示要设置的属性,第二个参数表示该属性要设置成的值(本例中用数组表示)。 • glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Imodel_ambient); • glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE,Imodel_twoside);

  16. 补充:光照模型包括四个部分的内容 • 全局环境光线(即那些充分散射,无法分清究竟来自哪个光源的光线)的强度; • 观察点位置是在较近位置还是在无限远处; • 物体正面与背面是否分别计算光照; • 镜面颜色(即GL_SPECULAR属性所指定的颜色)的计算是否从其它光照计算中分离出来,并在纹理操作以后在进行应用。

  17. 光照模型的属性如下: • GL_LIGHT_MODEL_AMBIENT表示全局环境光线强度,由四个值组成。属性GL_LIGHT_MODEL_AMBIENT指定OpenGL场景中的背景光,如果不指定,系统使用低强度的白色(0.2,0.2,0.2,1.0)光。 • GL_LIGHT_MODEL_LOCAL_VIEWER表示是否在近处观看,若是则设置为GL_TRUE,否则(即在无限远处观看)设置为GL_FALSE。 • GL_LIGHT_MODEL_TWO_SIDE表示是否执行双面光照计算。如果设置为GL_TRUE,则OpenGL不仅将根据法线向量计算正面的光照,也会将法线向量反转并计算背面的光照。 • GL_LIGHT_MODEL_COLOR_CONTROL表示颜色计算方式。如果设置为GL_SINGLE_COLOR,表示按通常顺序操作,先计算光照,再计算纹理。如果设置为GL_SEPARATE_SPECULAR_COLOR,表示将GL_SPECULAR属性分离出来,先计算光照的其它部分,待纹理操作完成后再计算GL_SPECULAR。后者通常可以使画面效果更为逼真.

  18. 步骤3:启动光源函数: glEnable • 使用glEnable函数可以开启这些光源。 如:glEnable(GL_LIGHT0);可以开启第0号光源。 • 使用glDisable函数则可以关闭光源。 • 注意:一些OpenGL实现可能支持更多数量的光源,但总的来说,开启过多的光源将会导致程序运行速度的严重下降,

  19. 启动光源: • glEnable( GL_LIGHTING ); // 启用光照glEnable( GL_LIGHT0 ); // 启用指定光源

  20. 步骤四:设置材质属性函数:glMaterialfv • 用glMaterialfv(GLenum face, GLenum pname, Type* param)函数设置. • /*设置前面材质*/ • glMaterialfv(GL_FRONT,GL_DIFFUSE,front_mat_diffuse); • glMaterialfv(GL_FRONT,GL_SPECULAR,front_mat_specular); • glMaterialfv(GL_FRONT,GL_SHININESS,front_mat_shininess); • /*设置后面材质*/ • glMaterialfv(GL_BACK,GL_DIFFUSE,back_mat_diffuse); • glMaterialfv(GL_BACK,GL_SPECULAR,back_mat_specular); • glMaterialfv(GL_BACK,GL_SHININESS,back_mat_shininess);

  21. 材质知识点补充: • 材质与光源相似,也需要设置众多的属性。不同的是,光源是通过glLight*函数来设置的,而材质则是通过glMaterial*函数来设置的。

  22. 材质函数: • glMaterial*函数有三个参数。 • 第一个参数表示指定哪一面的属性。可以是GL_FRONT、GL_BACK或者GL_FRONT_AND_BACK。分别表示设置“正面”“背面”的材质,或者两面同时设置 • 第二、第三个参数与glLight*函数的第二、三个参数作用类似,表示属性和属性值。 • 下面分别说明glMaterial*函数可以指定的材质属性。

  23. (1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。 • 这三个属性与光源的三个对应属性类似,每一属性都由四个值组成。 • GL_AMBIENT表示各种光线照射到该材质上,经过很多次反射后最终遗留在环境中的光线强度(颜色)。 • GL_DIFFUSE表示光线照射到该材质上,经过漫反射后形成的光线强度(颜色)。 • GL_SPECULAR表示光线照射到该材质上,经过镜面反射后形成的光线强度(颜色)。通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,可以达到比较真实的效果。 • 使用GL_AMBIENT_AND_DIFFUSE可以同时设置GL_AMBIENT和GL_DIFFUSE属性。

  24. (2)GL_SHININESS属性。 • 该属性只有一个值,称为“镜面指数”,取值范围是0到128。该值越小,表示材质越粗糙,点光源发射的光线照射到上面,也可以产生较大的亮点。该值越大,表示材质越类似于镜面,光源照射到上面后,产生较小的亮点。

  25. (3)GL_EMISSION属性。 • 该属性由四个值组成,表示一种颜色。OpenGL认为该材质本身就微微的向外发射光线,以至于眼睛感觉到它有这样的颜色,但这光线又比较微弱,以至于不会影响到其它物体的颜色。

  26. (4)GL_COLOR_INDEXES属性。 • 该属性仅在颜色索引模式下使用,由于颜色索引模式下的光照比RGBA模式要复杂,并且使用范围较小,这里不做讨论。

  27. 一、OpenGL颜色

  28. 二、OpenGL光照

  29. 三、材质

  30. 四、纹理映射

  31. 实例:三个不同材质球体

  32. 函数: glShadeModel • glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式。 • 参数一般为GL_SMOOTH(默认),GL_FLAT。OpenGL默认是将制定的两点颜色进行插值,绘制之间的其他点。 • 如果两点的颜色相同,使用两个参数效果相同。如果两点颜色不同,GL_SMOOTH会出现过渡效果,GL_FLAT 则只是以指定的某一点的单一色绘制其他所有点。

  33. glDepthFunc函数 • glDepthFunc()来设置深度测试函数 void glDepthFunc(GLenum func)   比较常用的深度测试函数有 GL_LESS 和 GL_LEQUAL 两者的区别在于当深度相同时是显示新的象素 还是老的象素。

  34. 注意: • glDepthFunc函数在每次绘制的时候都需要调用下

  35. 函数:glMatrixMode • glMatrixMode函数指定哪一个矩阵是当前矩阵void glMatrixMode(GLenum mode) • 参数mode 指定哪一个矩阵堆栈是下一个矩阵操作的目标,可选值: GL_MODELVIEW、GL_PROJECTION、GL_TEXTURE. • 说明glMatrixMode设置当前矩阵模式:GL_MODELVIEW,对模型视景矩阵堆栈应用随后的矩阵操作. GL_PROJECTION,对投影矩阵应用随后的矩阵操作. GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作. • glMatrixMode  与glLoadIdentity()一同使用glLoadIdentity():该函数的功能是重置当前指定的矩阵为单位矩阵。  在glLoadIdentity()之后我们为场景设置了透视图。glMatrixMode(GL_MODELVIEW)设置当前矩阵为模型视图矩阵,模弄视图矩阵储存了有关物体的信。

  36. 函数glColorMaterial  表示使用材质色跟踪当前颜色,指定了要改变的材质的属性,然后调用glColor*()去设置这些属性的值。glColor里的参数就是设置的值 • 函数: • void glColorMaterial(GLenum face,GLenum mode) • 参数的取值: face的取值: GL_FRONT 、GL_BACK 、GL_FRONT_AND_BACK mode的取值: GL_AMBIENT、 GL_DIFFUSE GL_AMBIENT_AND_DIFFUSE、 GL_SPECULAR GL_EMISSION

  37. 问题: • glColorMaterial需要在glEnable(GL_COLOR_MATERIAL);以后才可以用glColor设置材质,这时候的材质就是glColor*的值,如果没有Enable,那么就不能控制颜色的过渡值,颜色由最初给定的值来确定。

  38. 如果去掉这两句: // glColorMaterial(GL_FRONT,GL_AMBIENT); //glEnable(GL_COLOR_MATERIAL);效果如下:三只小球一样的颜色。这种颜色是由这几句语句决定的:glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse); glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular); glMaterialfv(GL_FRONT,GL_SHININESS,high_shininess); glMaterialfv(GL_FRONT,GL_EMISSION,no_mat);

  39. 注意: • 注释了// glColorMaterial(GL_FRONT,GL_AMBIENT); //glEnable(GL_COLOR_MATERIAL);语句后,无论怎么改变下面的值,都不能改变小球的颜色。 • GLfloat no_mat[]={0.0,0.0,0.0,1.0}; • GLfloat mat_grey_ambient[]={0.5,0.5,0.5,1.0}; • GLfloat mat_red_ambient[]={0.0,0.0,1.0,1.0};

  40. 可以通过以下修改定义颜色的语句来观察小球的颜色变化:可以通过以下修改定义颜色的语句来观察小球的颜色变化: • GLfloat light_position[]={0.0,3.0,6.0,0.0};//定义一行四列的数组 • GLfloat material_diffuse[]={0.8,0.2,0.5,1.0};//其实是控制环境光的颜色(除了高光外) • GLfloat material_specular[]={1.0,1.0,1.0,1.0};//其实是控制高光点的颜色: 如改变这个数组的值: GLfloat material_diffuse[]={0.0,0.0,0.5,1.0}; //其实是控制环境光的颜色(除了高光外)

  41. 实例:

  42. 本例总结: • 当需要改变场景中大部分方面的单个材质时,最好调用glColorMaterial() 。 • 当修改不只一个材质参数,最好调用glMaterial*()。

  43. 总结1:概念 • 环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向,但当特定的光源关闭后,它们将消失. • 全局环境光——它们并非来自特定的光源,这些光经过了多次散射,已经无法确定其光源位于何处. • 散射光——来自同一方向,照射到物体表面后,将沿各个方向均匀反射,因此,无论从哪个方向观察,表面的亮度都相同. • 镜面反射光——来自特定方向,也被反射到特定方向.镜面反射度与之相关. • 材质发射光——用于模拟发光物体.在OpenGL光照模型中,表面的发射光增加了物体的亮度,它不受光源的影响,另外,发射光不会给整个场景中增加光线.

  44. 总结2: • OpenGL光照模型将光照分为四个独立的部分:环境光,散射光,镜面反射光和发射光,这四种光被分别计算,然后叠加起来. • 光线的R,G,B值表示各分量的强度,材质的R,G,B值表示材质对相应分量的反射比例. • 定向光源不存在三种光线的衰减,但是定位光源存在衰减. • 被照射的物体不会向其它物体发出光线.

  45. 总结3:OpenGL光照中的默认值 • 光源的环境光默认为(0.0,0.0,0.0,1.0),即没有环境光. • 光源的散射光默认为(1.0,1.0,1.0,1.0),即存在白色散射光. • 光源的环境反射光默认值有两种情况,一种对应于光源GL_LIGNT0,其GL_SPECULAR为(1.0,1.0,1.0,1.0),即白色光;另一种对应于其它光源,其默认值为(0.0,0.0,0.0,0.0).一般情况下,光源的GL_SPECULAR应该和GL_DIFFUSE值相同. • 默认情况下,定位光源向所有方向发射光,但可以将其设置为聚光灯,使之在锥体内发光. • 光照模型中,全局环境光默认为(0.2,0.2,0.2,1.0),即存在微弱的白光;视点位置默认为0.0或者GL_FALSE,即无穷远处;默认采用单面光照,即GL_LIGHT_MODEL_TWO_SIDE为0.0或GL_FALSE(在对物体存在切割时,要启用双面光照);默认情况下,镜面反射颜色在纹理映射之前完成,即GL_LIGHT_MODEL_COLOR_CONTROL的值为GL_SINGLE_COLOR. • 材质属性的默认值:GL_AMBIENT (0.2,0.2,0.2,1.0); GL_DIFFUSE (0.8,0.8,0.8,1.0); GL_SPECULAR (0.0,0.0,0.0,1.0); GL_SHINNESS 0.0; GL_EMISSION (0.0,0.0,0.0,1.0).

  46. gluLookAt()函数:定义了视点矩阵 • void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz); • gluLookAt()共有九个参数,分别是眼睛的位置,眼睛朝向的位置,以及相片朝上的方向。 • 这个函数是对模型矩阵进行变换(GL_MODELVIEW),而gluPerspective函数是对投影矩阵进行变换(GL_PROJECTION)。 可以用gluPerspective函数设置近平面、远平面

More Related