OpenGL入门学习之七——使用光照来表现立体感
OpenGL中的光照技术研究
OpenGL中的光照技术研究摘要:光照处理是增强图形真实感的重要组成部分,主要研究了如何在场景中添加OpenGL光照,介绍了添加光照的基本步骤以及实现方法,并对如何设置物体的材质属性作了简要介绍。
关键词:光照;真实感;OpenGL;材质0 引言当观察一个物体时,所看到的颜色是基于光子的分布而形成的,正是这些光子刺激了人眼圆锥细胞。
这些光子可能来自单个光源,也可能来自多个光源。
有些光子被表面所吸收,有些光子则被表面所反射。
不同的表面所具有的属性不同。
物体本身如果是用光滑的材质所组成,在此情况下就会反射更多的光,人的眼睛因此也将接受到更多的光子。
如果物体是由粗糙的材质所组成,更多的光子会被其吸收或者被反射出视野之外,因此眼睛就不会接受到很多的光子,物体就会比较暗。
用OpenGL在模拟光照时,通过将光近似地分解成红、绿和蓝色分量来计算光和光照。
也就是说,一个光的颜色由此光中的红、绿和蓝色分量的数量决定。
当光照射到一个表面时,OpenGL根据其表面的材质来确定此表面所应该反射的光的红、绿和蓝色分量的百分比数量。
1 OpenGL中光的类型(1)环境光。
环境光并不来自任何特定的方向。
它来自某个光源,但光线却是在房间或场景中四处反射,没有方向性可言。
由环境光所照射的物体在所有方向上的所有表面都是均匀照亮的。
(2)散射光。
散射光来自于一个特定的方向,但它均匀地在一个表面反射开来。
虽然光是均匀反射的,但受到光线直接指向的物体表面还是比其它从某个角度受到光线掠过的表面更亮一些。
(3)镜面光。
镜面光也是有方向的,但它的反射角度很锐利,是沿一个特定的方向。
高强度镜面光趋向于在它所照射的表面上形成一个亮点。
(4)发射光。
带有发射光的物体看起来就好像自身会发光,只不过这样的光不会对场景中的其它物体产生影响。
在OpenGL 中,发射光增加了物体的亮度,但是任何光源都不会影响发射光。
2 OpenGL中添加光照的步骤在OpenGL中添加光照需要遵循以下步骤:①为每个物体的每个顶点计算法向量,法线确定了物体相对于光源的指向;②创建、选择并定位所有的光源;③创建并选择一种光照模型;④为场景中的物体定义材质属性。
浅谈OpenGL中的光照技术
浅谈OpenGL中的光照技术下面的这边文章,让我对OpenGL中的光照有了新的认识OpenGL场景中模型颜色的产生,大致为如下的流程图所描述:(1)当不开启光照时,使用顶点颜色来产生整个表面的颜色。
用glShadeModel可以设置表面内部像素颜色产生的方式。
GL_FLAT/GL_SMOOTH.(2)一般而言,开启光照后,在场景中至少需要有一个光源(GL_LIGHT0.。
.GL_LIGHT7)通过glEnable(GL_LIGHT0)glDisable(GL_LIGHT0)来开启和关闭指定的光源。
--- 全局环境光---GLfloat gAmbient[]= {0.6,0,6,0,6,1.0};glLightModelfv(GL_LIGHT_MODEL_AMBIENT,gAmbient);(3)设置光源的光分量-- 环境光/漫色光/镜面光默认情况下,GL_LIGHT0.。
.GL_LIGHT7 的GL_AMBIENT值为(0.0,0.0,0.0,1.0); GL_LIGHT0的GL_DIFFUSE和GL_SPECULAR值为(1.0,1.0,1.0,1.0),GL_LIGHT1.。
.GL_LIGHT7 的GL_DIFFUSE和GL_SPECULAR值为(0.0,0.0,0.0,0.0)。
GLfloat lightAmbient[]= {1.0,1.0,1.0,1.0};GLfloat lightDiffuse[]= {1.0,1.0,1.0,1.0};GLfloat lightSpecular[]= {0.5,0.5,0.5,1.0};glLightfv(GL_LIGHT0,GL_AMBIENT,lightAmbient);glLightfv(GL_LIGHT0,GL_DIFFUSE,lightDiffuse);glLightfv(GL_LIGHT0,GL_SPECULAR,lightSpecular);(4)设置光源的位置和方向-- 平行光-- 没有位置只有方向GLfloat lightPosiTIon[]= {8.5,5.0,-2.0,0.0}; // w=0.0。
OpenGL渲染技术初探
OpenGL渲染技术初探OpenGL是一种跨平台的图形渲染API,可以应用于不同操作系统和硬件设备。
因此,在计算机图形学中,它被广泛应用于三维图形和游戏开发中。
在本文中,我们将初步了解OpenGL的基本概念和渲染技术。
1. OpenGL的基本概念OpenGL的主要功能是渲染三维场景,并将其转换为二维像素图像以在屏幕上显示。
在渲染过程中,OpenGL将图形对象在网格中进行分割,并使用虚拟摄像机来定义视角。
然后,OpenGL使用光照、阴影和材质等技术来计算图形对象的外观。
在OpenGL中,图形对象由带有顶点信息的几何形状表示。
然后,这些形状被渲染成三角形模型,以便于OpenGL进行快速渲染。
此外,属性如颜色、纹理、光照和材质等也可以与对象相关联,以影响对象的外观。
除此之外,在OpenGL中还有很多其他的概念和技术,如纹理贴图、深度测试、逐像素光照和多重采样等。
这些技术能够让OpenGL实现更复杂的渲染效果。
2. OpenGL的渲染过程OpenGL的渲染过程通常包括以下步骤:①设置视角和投影:在OpenGL中,我们需要设置虚拟摄像机的位置和方向,以及投影方式,以定义图形对象的显示效果和视角。
②设置顶点信息:在OpenGL中,我们需要为图形对象准备带有顶点信息的几何形状,包括坐标、法线、颜色和纹理坐标等。
③设置着色器:在OpenGL中,我们需要设置着色器来处理图形对象的外观和动画效果。
其中,顶点着色器用于对顶点信息进行处理,而片元着色器用于对像素信息进行处理。
④定义纹理:在OpenGL中,我们可以通过定义纹理来为图形对象添加色彩和纹理效果。
纹理可以是图像、位图或生成的纹理等。
⑤应用光照:在OpenGL中,我们可以使用光照技术来模拟光照效果。
通过定义光源和材质,我们可以模拟不同的光照效果,如漫反射、镜面光反射和环境光等。
⑥渲染图像:在OpenGL中,我们需要将定义好的图形对象通过逐个像素的方式渲染成屏幕上的二维图像。
OpenGL光照
简单光照模型
当光照射到一个物体表面上时,会出现三种情 形。
– 首先,光可以通过物体表面向空间反射,产生反射光。 – 其次,对于透明体,光可以穿透该物体并从另一端射
出,产生透射光。 – 最后,部分光将被物体表面吸收而转换成热。
在上述三部分光中,仅仅是透射光和反射光能够进入人 眼产生视觉效果。简单光照模型只考虑被照明物体表 面的反射光影响,假定物体表面光滑不透明且由理想 材料构成,环境假设为由白光照明。
glEnable(GL_LIGHTING);
若使光照无效,则调用gDisable(GL_LIGHTING)可 关闭当前光照。然后,必须使所定义的每个光源有效, 例中只用了一个光源,即:
glEnable(GL_LIGHT0);
其它光源类似,只是光源号不同而已。
• 材质颜色
材质
OpenGL中,材质的定义与光源的定义很相似,是通 过定义材料对红、绿、蓝三色光的反射率来近似定义材 料的颜色。象光源一样,材料颜色也分成环境、漫反射 和镜面反射成分,它们决定了材料对环境光、漫反射光 和镜面反射光的反射程度。
在进行光照计算时,材料对环境光的反射率与每个进 入光源的环境光结合,对漫反射光的反射率与每个进入 光源的漫反射光结合,对镜面光的反射率与每个进入光 源的镜面反射光结合。
对环境光与漫反射光的反射程度决定了材料的颜色, 并且它们很相似。对镜面反射光的反射率通常是白色或 灰色(即对镜面反射光中红、绿、蓝的反射率相同)。 镜面反射高光最亮的地方将变成具有光源镜面光强度的 颜色。例如一个光亮的红色塑料球,球的大部分表现为 红色,光亮的高光将是白色的。
OpenGL光组成
• 漫射光来自一个方向,它垂直于物体时比倾斜时 更明亮。一旦它照射到物体上,则在各个方向上 均匀地发散出去。于是,无论视点在哪里它都一 样亮。来自特定位置和特定方向的任何光,都可 能有散射成分。
第六讲_OpenGL编程技术-光照
6.6.1、光照模型 ◇ 介绍例程:ep_7_1_光照球
6.6.1、光照模型 ◇ OpenGL光组成 在OpenGL简单光照模型中的几种光分为:辐射光 (Emitted Light)、环境光(Ambient Light)、漫 射光(Diffuse Light)、镜面光(Specular Light)。 辐射光是最简单的一种光,它直接从物体发出并 且不受任何光源影响。 环境光是由光源发出经环境多次散射而无法确定 其方向的光,即似乎来自所有方向。一般说来,房间 里的环境光成分要多些,户外的相反要少得多,因为 大部分光按相同方向照射,而且在户外很少有其他物 体反射的光。当环境光照到曲面上时,它在各个方向 上均等地发散(类似于无影灯光)。
光学反射模型
通常物体表面的反射光可以认为包含三个分量:对环境光的 反射、对特定光源的漫反射和镜面反射。
(a) 漫反射
(b) 理想镜面反射
(c) 一般光滑表面的镜面反射
(d) 理想镜面反射方向 与视线方向的夹角
图6-6 光学反射模型
环境光的反射: 环境光(ambient light)来自周围环境(如墙面)散射的光,在 空间近似均匀分布,入射至物体表面后向空间各个方向均匀 反射出去。物体对环境光的反射分量表示: 其中Ia是入射的环境光亮度,Ka是环境光漫反射系数,它与物 体表面性质有关。如果简单光照模型中仅考虑环境光的反射分 量,则物体表面的亮度是一个恒定值,没有明暗的自然过渡。 散射(diffuse reflection): 散射分量表示特定光源在物体表面的反射光中那些向空间 各个方向均匀反射出去的光。兰伯特(Lambert)余弦定律指出: 当点光源照射到一个散射体时,其表面反射光亮度和光源入射 角(入射光线和表面法矢量的夹角)的余弦成正比,即 I K d I l cos( ) 0 0 Kd 1
OpenGL之使用光照和材质
使用了光照和材质可以使物体更逼真,具有立体感。
例4就是没有使用光照使呈现在我们眼前的物体茶壶和立方体没有立体感。
例6:绘制三个使用不同材质的球体。
函数myInit中:
·glLight设置光源的参数。
有三个参数,第一个参数指定光照的数目,最大为8。
第二个参数为光照的单值光源参数。
第三个参数为赋给第二个参数的值,本例中即为将light_position的值赋值给GL_POSITION。
display函数中:
·glMaterial为光照模型指定材质参数。
第一个参数为改变材质的面,其值必为GL_FRONT, GL_BACK或GL_FRONT_AND_BACK中的一个。
第二个参数为需要改变的材质参数。
第三个参数为赋给参数二的值或指向值的指针。
本例中均为指针。
·glColorMateria使材质色跟踪当前颜色。
第一个参数指定哪一个面需要使材质色跟踪当前颜色。
第二个参数指定哪个参数需要跟踪颜色。
OpenGL(七)光照模型及设置
OpenGL(七)光照模型及设置OpenGL把现实世界中的光照系统近似归为三部分,分别是光源、材质和光照环境。
光源就是光的来源,是“光”这种物质的提供者;材质是指被光源照射的物体的表⾯的反射、漫反射(OpenGL不考虑折射)特性;材质反映的是光照射到物体上后物体表现出来的对光的吸收、漫反射、反射等性能;光照环境反应环境中所有光源发出的光经过⽆数次反射、漫反射之后整体环境所表现出来的光照效果。
指定合适的光照环境参数可以使得最后形成的画⾯更接近于真实场景。
⼀、光源光照模型OpenGL中的光照模型中的反射光分为三个分量,分别是环境反射光(Ambient Light)、漫反射光(Diffuse Light)和镜⾯反射光(Specular Light)。
环境光Ambient:是由光源发出经环境多次散射⽽⽆法确定其⼊射⽅向的光,即似乎来⾃所有⽅向。
其特征是⼊射⽅向和出射⽅向均为任意⽅向。
漫射光Diffuse:来⾃特定⽅向,它垂直于物体时⽐倾斜时更明亮。
⼀旦它照射到物体上,则在各个⽅向上均匀地发散出去,效果为⽆论视点在哪⾥它都⼀样亮,其特征是⼊射⽅向唯⼀、出射⽅向为任意⽅向。
镜⾯光Specular:来⾃特定⽅向并沿另⼀⽅向反射出去,⼀个平⾏激光束在⾼质量的镜⾯上产⽣100%的镜⾯反射,其特征是⼊射⽅向和出射⽅向均唯⼀。
创建光源OpenGL中⽤函数glLightfv来创建光源,函数原型是:void glLightfv (GLenum light, GLenum pname, const GLfloat *params)第⼀个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7。
第⼆个参数pname指定光源特性,这个参数的具体信息见下表所⽰。
第三个参数设置相应的光源特性值。
例如下边定义了⼀个位置在(0,0,0),没有环境光,镜⾯反射光和漫反射光都为⽩光的光源:GLfloat light_position[] = { 0.0, 0.0, 0.0, 0.0 };GLfloat light_ambient [] = { 0.0, 0.0, 0.0, 1.0 };GLfloat light_diffuse [] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };glLightfv(GL_LIGHT0, GL_POSITION, light_position);glLightfv(GL_LIGHT0, GL_AMBIENT , light_ambient );glLightfv(GL_LIGHT0, GL_DIFFUSE , light_diffuse );glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);光源的位置坐标采⽤齐次坐标(x, y, z, w)设置。
OpenGL中的光照模型
OpenGL中的光照模型一、OpenGL的光照模型在OpenGL的简单光照模型中反射光可以分成三个分量,环境反射光(Ambient Light)、漫反射光(Diffuse Light)和镜面反射光(Specular Light):a、环境光Ambient,是由光源发出经环境多次散射而无法确定其入射方向的光,即似乎来自所有方向。
当环境光照到曲面上时,它在各个方向上均等地发散(类似于无影灯光)。
特征:入射方向和出射方向均为任意方向。
b、漫射光Diffuse,来自特定方向,它垂直于物体时比倾斜时更明亮。
一旦它照射到物体上,则在各个方向上均匀地发散出去,效果为无论视点在哪里它都一样亮。
特征:入射方向唯一、出射方向为任意方向。
c、镜面光Specular,来自特定方向并沿另一方向反射出去,一个平行激光束在高质量的镜面上产生100%的镜面反射。
特征:入射方向和出射方向均唯一。
二、创建光源定义光源特性的函数:glLight*(light , pname, param)其中第一个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7;第二个参数pname指定光源特性,这个参数的辅助信息见表1所示;最GL_LIGHT0,其他几个光源的GL_DIFFUSE和GL_SPECULAR缺省值为(0.0,0.0,0.0,1.0)。
三、启用光源和明暗处理如果光照无效,则只是简单地将当前颜色映射到当前顶点上去,不进行法向、光源、材质等复杂计算。
要启用光照或关闭光照,调用函数:glEnable(GL_LIGHTING) 或glDisable(GL_LIGHTING)。
启用光照后必须调用函数glEnable(GL_LIGHT0) ,使所定义的光源有效。
其它光源类似,只是光源号不同而已。
在OpenGL中,用单一颜色处理的称为平面明暗处理(Flat Shading),用许多不同颜色处理的称为光滑明暗处理(Smooth Shading),也称为Gourand明暗处理(Gourand Shading)。
浅谈OpenGL中的光照技术
浅谈OpenGL中的光照技术下面的这边文章,让我对OpenGL中的光照有了新的认识OpenGL场景中模型颜色的产生,大致为如下的流程图所描述:(1)当不开启光照时,使用顶点颜色来产生整个表面的颜色。
用glShadeModel可以设置表面内部像素颜色产生的方式。
GL_FLAT/GL_SMOOTH.(2)一般而言,开启光照后,在场景中至少需要有一个光源(GL_LIGHT0.。
.GL_LIGHT7)通过glEnable(GL_LIGHT0)glDisable(GL_LIGHT0)来开启和关闭指定的光源。
--- 全局环境光---GLfloat gAmbient[]= {0.6,0,6,0,6,1.0};glLightModelfv(GL_LIGHT_MODEL_AMBIENT,gAmbient);(3)设置光源的光分量-- 环境光/漫色光/镜面光默认情况下,GL_LIGHT0.。
.GL_LIGHT7 的GL_AMBIENT值为(0.0,0.0,0.0,1.0); GL_LIGHT0的GL_DIFFUSE和GL_SPECULAR值为(1.0,1.0,1.0,1.0),GL_LIGHT1.。
.GL_LIGHT7 的GL_DIFFUSE和GL_SPECULAR值为(0.0,0.0,0.0,0.0)。
GLfloat lightAmbient[]= {1.0,1.0,1.0,1.0};GLfloat lightDiffuse[]= {1.0,1.0,1.0,1.0};GLfloat lightSpecular[]= {0.5,0.5,0.5,1.0};glLightfv(GL_LIGHT0,GL_AMBIENT,lightAmbient);glLightfv(GL_LIGHT0,GL_DIFFUSE,lightDiffuse);glLightfv(GL_LIGHT0,GL_SPECULAR,lightSpecular);(4)设置光源的位置和方向-- 平行光-- 没有位置只有方向GLfloat lightPosiTIon[]= {8.5,5.0,-2.0,0.0}; // w=0.0glLightfv(GL_LIGHT0,GL_POSITION,lightPosiTIon);-- 点光源-- 有位置没有方向GLfloat lightPosiTIon[]= {8.5,5.0,-2.0,1.0}; // w不为0glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);-- 聚光灯-- 有位置有方向GLfloat lightPosition[]= {-6.0,1.0,3.0,1.0}; // w不为0glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);GLfloat lightDirection[]= {1.0,1.0,0.0};glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,lightDirection); // 聚光灯主轴方向spot directionglLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0); // cutoff角度spot cutoff** 平行光不会随着距离d增加而衰减,但点光源和聚光灯会发生衰减。
使用open GL在绘制球体的基础上增加光照和材质设置
(计算机图形学)实验报告实验名称使用open GL在绘制球体的基础上增加光照和材质设置实验时间年月日专业班级学号:姓名:成绩教师评语:一、实验目的1、了解并学习open GL的编程;2、掌握在open GL生成图形的基本思想和基本步骤;3、使用open GL具体生成简单的三维立体图形;4、在生成的三维立体的图形上面增加光照和材质的设置。
二、实验原理在上一个实验的基础上,对绘制出来的球体进行光照和材质的设置使其看起来更有立体感,其中对我们有以下几条要求:1、理解环境光,漫反射光和镜面反射光的光照模型2、理解phong光照模型,熟练掌握opengl中设置光照的方法3、掌握材质的设置方式一.材质的指定材质和灯光一样有三种属性:环境属性,漫反射属性和镜面反射属性,这些属性确定了材质反射灯光的多少。
设置材质和设置光照很相似,设置材质的函数是glMaterial*()glMaterial{if}v(face, pname, value)face :指明对物体的哪些面进行材质设置GL_FRONTGL_BACKGL_FRONT_AND_BACKPname:要设置的材质属性GL_AMBIENT 设置材料的环境颜色GL_DIFFUSE 设置材料的漫反射颜色GL_SPECULAR 设置材料的镜面反射颜色GL_AMIBIENT_AND_DIFFUSE 设置材料的环境和漫反射颜色GL_SHININESS 设置镜面指数GL_EMISSION 设置材料的发散颜色GL_COLOR_INDEXES 设置环境,漫反射和镜面反射的颜色索引1.通常,GL_AMBIENT 和GL_DIFFUSE 都取相同的值,可以达到比较真实的效果。
使用GL_AMBIENT_AND_DIFFUSE 可以同时设置 GL_AMBIENT 和 GL_DIFFUSE属性。
2.GL_SHININESS属性。
该属性只有一个值,称为“镜面指数”,取值范围是 0到128。
实验7 OpenGL光照
实验7 OpenGL光照一、实验目的了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效果。
二、实验内容(1)下载并运行Nate Robin教学程序包中的lightmaterial 程序,试验不同的光照与材质系数;(2)运行示范代码1,了解光照与材质函数使用。
三、实验原理为在场景中增加光照,需要执行以下步骤:(1)设置一个或多个光源,设定它的有关属性;(2)选择一种光照模型;(3)设置物体的材料属性。
具体见教材第8章8.6节用OpenGL生成真实感图形的相关内容。
四、实验代码#include<GL/glut.h>#include<stdlib.h>static int year =0,day=0;void init(void){GLfloat mat_specular[]={1.0,1.0,1.0,1.0};GLfloat mat_shininess[]={50.0};GLfloat light_position[]={1.0,1.0,1.0,0.0};GLfloat white_light[]={1.0,1.0,1.0,1.0};GLfloat Light_Model_Ambient[]={0.2,0.2,0.2,1.0};glClearColor(0.0,0.0,0.0,0.0);glShadeModel(GL_SMOOTH);//glMaterialfv(材质指定,单值材质参数,具体指针);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);//镜面反射光的反射系数glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);//镜面反射指数//glLightfv(光源,属性名,属性值);glLightfv(GL_LIGHT0, GL_POSITION, light_position); //光源位置glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); //漫放射光分量强度glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); //折射光强度glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Light_Model_Ambient );//光源2 GL_LIGHT1GLfloat mat_specular1[]={1.0,1.0,1.0,1.0};GLfloat mat_shininess1[]={50.0};GLfloat light_position1[]={0.0,0.0,0.0,0.0};GLfloat red_light[]={1.0,0.0,0.0,1.0};GLfloat Light_Model_Ambient1[]={0.2,0.2,0.2,1.0};glLightfv(GL_LIGHT1, GL_POSITION, light_position1); //光源位置glLightfv(GL_LIGHT1, GL_DIFFUSE, red_light); //漫放射光分量强度glLightfv(GL_LIGHT1, GL_SPECULAR, red_light); //折射光强度glLightModelfv(GL_LIGHT_MODEL_AMBIENT,Light_Model_Ambient 1);//开启灯光glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_LIGHT1);glEnable(GL_DEPTH_TEST);}void display(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glPushMatrix();// 定义太阳的材质并绘制太阳{GLfloat sun_mat_ambient[] = {1.0f, 0.0f, 0.0f, 1.0f}; //定义材质的环境光颜色,偏红色GLfloat sun_mat_diffuse[] = {0.5f, 0.5f, 0.0f, 1.0f}; //定义材质的漫反射光颜色,偏红色GLfloat sun_mat_specular[] = {1.0f,0.0f, 0.0f, 1.0f}; //定义材质的镜面反射光颜色,红色GLfloat sun_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f}; //定义材质的辐射光颜色,为0GLfloat sun_mat_shininess = 32.0f;glMaterialfv(GL_FRONT,GL_AMBIENT,sun_mat_ambient);glMaterialfv(GL_FRONT,GL_DIFFUSE,sun_mat_diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,sun_mat_specular);glMaterialfv(GL_FRONT,GL_EMISSION,sun_mat_emission);glMaterialf(GL_FRONT,GL_SHININESS,sun_mat_shininess);glutSolidSphere(0.5,40,16);//太阳glRotatef((GLfloat) year,0.0,1.0,0.0);}glPushMatrix();{GLfloat earth_mat_ambient[] = {0.0f, 0.0f, 1.0f,1.0f}; //定义材质的环境光颜色,偏蓝色GLfloat earth_mat_diffuse[] = {0.0f, 0.0f, 0.5f,1.0f}; //定义材质的漫反射光颜色,偏蓝色GLfloat earth_mat_specular[] = {1.0f, 0.0f, 0.0f, 1.0f};//定义材质的镜面反射光颜色,红色GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f};//定义材质的辐射光颜色,为0GLfloat earth_mat_shininess = 30.0f;glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular);glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission);glMaterialf (GL_FRONT, GL_SHININESS,earth_mat_shininess);glTranslatef(0.8,0.0,0.0);glRotatef((GLfloat) day,0.0,1.0,0.5);//位置变化glutSolidSphere(0.2,20,8);//地球{GLfloat earth_mat_ambient[] = {0.0f, 1.0f, 0.0f, 1.0f}; //定义材质的环境光颜色,偏绿色GLfloat earth_mat_diffuse[] = {0.0f, 0.5f, 0.0f, 1.0f}; //定义材质的漫反射光颜色,偏绿色GLfloat earth_mat_specular[] = {1.0f, .0f, 0.0f, 1.0f}; //定义材质的镜面反射光颜色,红色GLfloat earth_mat_emission[] = {0.0f, 0.0f, 0.0f, 1.0f}; //定义材质的辐射光颜色,为0GLfloat earth_mat_shininess = 30.0f;glMaterialfv(GL_FRONT, GL_AMBIENT, earth_mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE, earth_mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, earth_mat_specular);glMaterialfv(GL_FRONT, GL_EMISSION, earth_mat_emission);glMaterialf (GL_FRONT, GL_SHININESS, earth_mat_shininess);glTranslatef(0.4,0.0,0.0);glRotatef((GLfloat) day,0.0,1.0,0.0);glutSolidSphere(0.1,20,8);//月亮}}glPopMatrix();glPopMatrix();glutSwapBuffers();glFlush();}void reshape(int w,int h){glViewport(0,0,(GLsizei) w,(GLsizei) h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if(w<=h){glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(G Lfloat)w,-10.0,10.0);}else{glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5,1.5,-10.0,10.0);}glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);}void keyboard(unsigned char key, int x,int y){switch (key){case 'd':day=(day+10)%360;glutPostRedisplay();break;case 'D':day=(day-10)%360;glutPostRedisplay();break;case 'y':year=(year + 5)%360;glutPostRedisplay();break;case 'Y':year=(year-5)%360;glutPostRedisplay();break;case 27:exit(0);break;default:break;}}int main(int argc,char **argv){glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);glutInitWindowSize(500,500);glutInitWindowPosition(100,100);glutCreateWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}五、实验结果以下是实验结果截图:六、实验分析实验中,两个主要函数,glMaterialfv(材质指定,单值材质参数,具体指针),设置图形材质,glLightfv(光源,属性名,属性值),用来设置光源。
第13讲 OpenGL 光照
glLightfv(GL_LIGHT0,GL_AMBIENT, LightAmbient); glLightfv(GL_LIGHT0,GL_DIFFUSE, LightDiffuse); glLightfv(GL_LIGHT0,GL_SPECULAR, LightSpecular);
光源的属性
位置
glLightf举例
GLfloat LightSpotExponent = 10.0f; GLfloat LightSpotCutoff = 20.0f; //聚光指数 //聚光角度
glLightf( GL_LIGHT1,GL_SPOT_EXPONENT, LightSpotExponent ); glLightf( GL_LIGHT1, GL_SPOT_CUTOFF, LightSpotCutoff );
选择光照模型
void glLightModeli(GLenum pname, GLint param); 功能:
选择光照模型
参数:
pname: 光照模型的类型 param: 该类型的值
返回值:无 备注:
pname可以取值为:
GL_LIGHT_MODEL_LOCAL_VIEWER //观察点是否无穷远(GL_FALSE) GL_LIGHT_MODEL_TWO_SIDE //单面还是双面光照(GL_FALSE )
kc+kld+kqd2
kc = GL_CONSTANT_ATTENUATION kl = GL_LINEAR_ATTENUATION kq = GL_QUADRATIC_ATTENUATION d为光源位置与顶点之间的距离
例:
glLightf(GL_LIGHT5, GL_CONSTANT_ATTENUATION, 2.0); glLightf(GL_LIGHT5, GL_LINEAR_ATTENUATION, 1.0); glLightf(GL_LIGHT5, GL_QUADRATIC_ATTENUATION, 0.5);
OPenGL--光照
从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。
人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。
因此对于人类而言,光线很大程度上表现了物体的立体感。
请看图1,图中绘制了两个大小相同的白色球体。
其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。
左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。
图1OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。
但是在这之前,我们有必要了解一些基础知识。
一、建立光照模型在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。
这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。
就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。
比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。
不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。
OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。
光源就是光的来源,可以是前面所说的太阳或者电灯等。
材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。
光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。
在物理学中,光线如果射入理想的光滑平面,则反射后的光线是很规则的(这样的反射称为镜面反射)。
OpenGL中的颜色光照和材质
(2)GL_SHININESS属性。
GL_LIGHT_MODEL_COLOR_CONTROL表示颜色计算方式。如果设置为 GL_SINGLE_COLOR,表示按通常顺序操作,先计算光照,再计算纹理。 如果设置为GL_SEPARATE_SPECULAR_COLOR,表示将 GL_SPECULAR属性分离出来,先ቤተ መጻሕፍቲ ባይዱ算光照的其它部分,待纹理操作完成 后再计算GL_SPECULAR。后者通常可以使画面效果更为逼真.
步骤3:启动光源
函数: glEnable
使用glEnable函数可以开启这些光源。 如:glEnable(GL_LIGHT0);可以开启第0号光源。 使用glDisable函数则可以关闭光源。 注意:一些OpenGL实现可能支持更多数量的 光源,但总的来说,开启过多的光源将会导致 程序运行速度的严重下降,
(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属性。
GL_LIGHT0进行设置,第二个参数表示要设置的是漫反射光成分,第三个参 数则是一个数组(表示光照属性值)
opengl光源光照使用范例
OpenGL光源光照使用范例1. 光照模型环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向,但当特定的光源关闭后,它们将消失.全局环境光——每个光源都能对场景提供环境光。
此外,还有一个环境光,它不来自任何特定的光源,称之为全局环境光。
这也就是为什么我们不加任何自定义光源,也能看见绘制的物体的原因。
散射光——来自同一方向,照射到物体表面后,将沿各个方向均匀反射,因此,无论从哪个方向观察,表面的亮度都相同. 主要通过设置GLfloat light_diffuse[] = { 0.0, 1.0, 0.0, 1.0 }来发射绿光镜面反射光——来自特定方向,也被反射到特定方向.镜面反射度与之相关.材质发射光——用于模拟发光物体.在OpenGL光照模型中,表面的发射光增加了物体的亮度,它不受光源的影响,另外,发射光不会给整个场景中增加光线.当光照射到一个物体表面上时,会出现三种情形。
首先,光可以通过物体表面向空间反射,产生反射光。
其次,对于透明体,光可以穿透该物体并从另一端射出,产生透射光。
最后,部分光将被物体表面吸收而转换成热。
在上述三部分光中,仅仅是透射光和反射光能够进入人眼产生视觉效果。
这里介绍的简单光照模型只考虑被照明物体表面的反射光影响,假定物体表面光滑不透明且由理想材料构成,环境假设为由白光照明。
一般来说,反射光可以分成三个分量,即环境反射、漫反射和镜面反射。
环境反射分量假定入射光均匀地从周围环境入射至景物表面并等量地向各个方向反射出去,通常物体表面还会受到从周围环境来的反射光(如来自地面、天空、墙壁等的反射光)的照射,这些光常统称为环境光(Ambient Light);漫反射分量表示特定光源在景物表面的反射光中那些向空间各方向均匀反射出去的光,这些光常称为漫射光(Diffuse Light);镜面反射光为朝一定方向的反射光,如一个点光源照射一个金属球时会在球面上形成一块特别亮的区域,呈现所谓“高光(Highlight)”,它是光源在金属球面上产生的镜面反射光(Specular Light)。
实验七 OpenGL光照效果
1.实验七OpenGL光照效果(选做)1.实验七:OpenGL光照效果。
2.实验目的:通过上机编程,熟悉并掌握OpenGL中光照效果的制造方法。
3.实验要求:(1)先做实验项目:实验六“OpenGL组合图形”。
(2)每人一组,独立完成。
(3)利用OpenGL提供的颜色、光源、材质设置,对实验六“OpenGL组合图形”中自己设计的物体设置绘制颜色和材质参数,并在场景中添加光源,形成一定的光照明暗效果。
4.实验原理及内容:在现实世界中,光线和物体的材质共同决定了物体在人眼中的效果。
OpenGL 中则涉及到绘制颜色、物体的材质参数、场景中的光源颜色和位置,以此达到一定的真实感光照效果。
(1)颜色:OpenGL通过指定红、绿、蓝(RGB)三个成分的各自亮度来确定颜色,有时还有第四个成分alpha:glColor*(red, green, blue[, alpha]);glColor()函数设置当前的绘图颜色,red、green和blue分别为红、绿、蓝的亮度,alpha为透明度,取值均为0.0~1.0。
在该函数之后绘制的所有物体都将使用该颜色。
(2)光线:OpenGL的光照模型中将光源分成四种:发射光:一个物体本身就是一个发光源,如太阳、电灯等,这种光不受其它任何光源的影响。
环境光:从光源出发后光线被环境多次反射,以致没有明确的方向,或者说来自于所有的方向。
被环境光照射的物体,各个表面都均等受光。
散射光:来自于某个方向,被物体表面均匀地反射,例如荧光照明、窗口射入的阳光等。
镜面光:来自于一个方向,被物体强烈地反射到另一个特定的方向。
高亮度的镜面光往往能在被照射的物体表面产生亮斑,如金属球上的高光区。
对于散射光和镜面光,入射角度、距离和衰减因子还会影响到最终的光照效果。
除了物体本身的发射光以外,通常意义上的光并不会是单纯的环境光、散射光或镜面光,而是由这三种类型的光混合组成的。
在OpenGL中,光也是采用RGBA值来定义的,分别描述光线中红绿蓝各成分的相对亮度。
三维图形的光照、贴图及阴影处理(OpenGL)
三维图形的光照、贴图及阴影处理(OpenGL)实验过程:一、在VS6.0中建立新工程。
1、新建一个Win32 Application的工程。
2、向工程项目添加C++源文件。
3、将OpenGL框架复制到文件中。
4、设置OpenGL窗口标题。
二、场景设置。
1、视线处于一具有地板及前、左、右三面墙壁的空间中。
2、空间顶部中央有一光源。
3、空间中央有一地球仪,不断旋转。
三、建立视口结构及视点属性。
1、在坐标系上建立视图结构。
如图。
2、参数设置。
窗口大小:800*600。
视口大小:800*600。
透视深度:0.1~100。
透视角:60°。
视点位置:(0.0, 2.0, 15.0)。
视线方向:z轴负方向。
视点上方向:y轴正方向。
3、调用函数glViewport()、gluPerspective()和gluLookAt()实现。
四、绘制三维图形。
1、开启深度测试模式。
为防止图形重叠时出现层次混乱,必须对绘制图形进行消隐处理。
直接调用函数glEnable(GL_DEPTH_TEST)开启深度测试。
2、绘制地面与墙壁。
调用OpenGL基本几何元素绘制过程glBegin(GL_QUADS)、glBegin(GL_QUAD_STRIP)绘制四个平面,坐标范围为:x: -10~10, y: -2~20, z: -10~10。
坐标系结构如图。
3、绘制地球仪。
设计函数void DrawEarth()实现地球仪的绘制,分别调用OpenGL球面绘制函数gluSphere()绘制地球形状、柱面绘制函数gluCylinder()绘制地轴两头形状。
(1)参数设置。
球面半径:2。
球面细度:水平100,垂直100。
柱面半径:0.05。
柱面高度:1。
柱面细度:水平50,垂直1。
(2)结构如图。
4、绘制模拟光源。
(1)绘制“灯罩”。
调用glBegin(GL_TRIANGLE_STRIP)绘制4个三角形,构成棱椎形灯罩的4个侧面。
(2)绘制“灯泡”。
如何在绘画中有效利用光影效果来营造立体感
如何在绘画中有效利用光影效果来营造立体感?在绘画中有效利用光影效果是创造立体感的关键之一。
下面是一些技巧和建议,帮助您在绘画中运用光影来增强立体效果:1. 观察现实世界:深入观察真实场景中的光影效果,注意光线的方向、强度和阴影的形状。
这将帮助您更好地理解光影的运作方式,并在绘画中准确地再现。
2. 对比明暗:在绘画中创造对比明暗的区域,以突出物体的立体感。
通过使用明亮的高光和深沉的阴影,您可以强调物体的体积和形状。
3. 渐变过渡:运用渐变过渡来平滑光影的变化。
通过绘制渐变的阴影,使物体看起来更加立体和流动。
4. 反射和折射:考虑光线在不同材质上的反射和折射效果。
不同的材质会对光线产生不同的影响,因此在绘画中注意到这些细节将增加真实感和立体感。
5. 注意光源:确定光源的位置和类型,如自然光、人造光等。
光源的位置将决定阴影的投射方向和形状。
6. 确定主要光源和次要光源:在决定光源位置后,可以考虑添加多个光源以增加画面的层次感和立体感。
7. 实践阴影技巧:掌握不同类型的阴影技巧,如锥形阴影、圆柱体阴影、透视阴影等。
这些技巧可以帮助您更好地表现物体的形状和立体感。
8. 使用对比色:通过对比色的运用来强调光影效果。
例如,在阴影部分添加一些暖色调,而在高光部分添加一些冷色调,这将增加画面的对比度和立体感。
9. 学习我们的作品:研究大师级我们的作品,观察他们是如何运用光影来创造立体感的。
学习他们的技巧和方法,将有助于您发展自己的绘画技能。
10. 反复实践:绘画是一个不断学习和实践的过程。
通过不断尝试和实践,您将更好地理解和掌握光影的运用,从而提高自己的绘画技能。
希望这些建议对您有所帮助!记住,绘画是一门艺术,没有固定的规则,尽情发挥并探索自己的风格和创意。
OpenGL
OpenGL Shader实现光照发光体特效⽬录内发光原理发光体实现扩展效果⼩太阳光源移动效果内发光原理内发光原理简单概况是:采样周边像素alpha取平均值叠加效果。
概括来说似乎好像特别简单,但需要⼀定的理解和消化。
发光物体可以当做是⼀个圆形对象,去采集圆形对象周边像素值。
例如已知圆形半径是R,⾓度是Angle,然后根据半径和⾓度推导算出当前像素坐标位置,⽤当前像素坐标位置得到透明度再去做计算。
但其实在中似乎已经介绍过了同样能够通过。
不同点在于阴影遮盖是利⽤圆形绘制向外部晕染⽽内发光效果是作⽤于内部。
发光体实现⾸先采⽤绘制圆的⽅法实现RGB叠加。
可以看到中⼼位置绘制圆的位置颜⾊较深,向外扩散颜⾊逐渐暗淡。
效果虽然不对但已经知道下⼀步该怎么实现了。
void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;uv -= 0.5;uv.x *= iResolution.x/iResolution.y;vec3 color = vec3(0.);float glow = length(uv);color += glow;gl_FragColor = vec4(color,1.);}通过取反操作,可⽤⼀个数除以length(uv)再相乘⼀个⼩数来稍微减⼩值的⼤⼩。
从最终结果可以看到所期望的效果。
对⽐之前效果展⽰相除相当于对原结果取反,原先内部是数值最⼩,相除之后内部数值变成最⼤。
void main() {vec2 uv = gl_FragCoord.xy / iResolution.xy;uv -= 0.5;uv.x *= iResolution.x/iResolution.y;vec3 color = vec3(0.);float glow = 0.05 * 3./length(uv);color += glow;gl_FragColor = vec4(color,1.);}但过渡效果泛⽩范围似乎过⼤了⼀些继续对原算法进⾏优化。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
OpenGL入门学习之七——使用光照来表现立体感2009-01-07 11:49从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。
人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。
因此对于人类而言,光线很大程度上表现了物体的立体感。
请看图1,图中绘制了两个大小相同的白色球体。
其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。
左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。
图1OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。
但是在这之前,我们有必要了解一些基础知识。
一、建立光照模型在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。
这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。
就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。
比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。
不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。
OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。
光源就是光的来源,可以是前面所说的太阳或者电灯等。
材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。
光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。
在物理学中,光线如果射入理想的光滑平面,则反射后的光线是很规则的(这样的反射称为镜面反射)。
光线如果射入粗糙的、不光滑的平面,则反射后的光线是杂乱的(这样的反射称为漫反射)。
现实生活中的物体在反射光线时,并不是绝对的镜面反射或漫反射,但可以看成是这两种反射的叠加。
对于光源发出的光线,可以分别设置其经过镜面反射和漫反射后的光线强度。
对于被光线照射的材质,也可以分别设置光线经过镜面反射和漫反射后的光线强度。
这些因素综合起来,就形成了最终的光照效果。
二、法线向量根据光的反射定律,由光的入射方向和入射点的法线就可以得到光的出射方向。
因此,对于指定的物体,在指定了光源后,即可计算出光的反射方向,进而计算出光照效果的画面。
在OpenGL中,法线的方向是用一个向量来表示。
不幸的是,OpenGL并不会根据你所指定的多边形各个顶点来计算出这些多边形所构成的物体的表面的每个点的法线(这话听着有些迷糊),通常,为了实现光照效果,需要在代码中为每一个顶点指定其法线向量。
指定法线向量的方式与指定颜色的方式有雷同之处。
在指定颜色时,只需要指定每一个顶点的颜色,OpenGL就可以自行计算顶点之间的其它点的颜色。
并且,颜色一旦被指定,除非再指定新的颜色,否则以后指定的所有顶点都将以这一向量作为自己的颜色。
在指定法线向量时,只需要指定每一个顶点的法线向量,OpenGL会自行计算顶点之间的其它点的法线向量。
并且,法线向量一旦被指定,除非再指定新的法线向量,否则以后指定的所有顶点都将以这一向量作为自己的法线向量。
使用glColor*函数可以指定颜色,而使用glNormal*函数则可以指定法线向量。
注意:使用glTranslate*函数或者glRotate*函数可以改变物体的外观,但法线向量并不会随之改变。
然而,使用glScale*函数,对每一坐标轴进行不同程度的缩放,很有可能导致法线向量的不正确,虽然OpenGL提供了一些措施来修正这一问题,但由此也带来了各种开销。
因此,在使用了法线向量的场合,应尽量避免使用glScale*函数。
即使使用,也最好保证各坐标轴进行等比例缩放。
三、控制光源在OpenGL中,仅仅支持有限数量的光源。
使用GL_LIGHT0表示第0号光源,GL_LIGHT1表示第1号光源,依次类推,OpenGL至少会支持8个光源,即GL_LIGHT0到GL_LIGHT7。
使用glEnable函数可以开启它们。
例如,glEnable(GL_LIGHT0);可以开启第0号光源。
使用glDisable函数则可以关闭光源。
一些OpenGL实现可能支持更多数量的光源,但总的来说,开启过多的光源将会导致程序运行速度的严重下降,玩过3D Mark的朋友可能多少也有些体会。
一些场景中可能有成百上千的电灯,这时可能需要采取一些近似的手段来进行编程,否则以目前的计算机而言,是无法运行这样的程序的。
每一个光源都可以设置其属性,这一动作是通过glLight*函数完成的。
glLight*函数具有三个参数,第一个参数指明是设置哪一个光源的属性,第二个参数指明是设置该光源的哪一个属性,第三个参数则是指明把该属性值设置成多少。
光源的属性众多,下面将分别介绍。
(1)GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR属性。
这三个属性表示了光源所发出的光的反射特性(以及颜色)。
每个属性由四个值表示,分别代表了颜色的R, G, B, A值。
GL_AMBIENT表示该光源所发出的光,经过非常多次的反射后,最终遗留在整个光照环境中的强度(颜色)。
GL_DIFFUSE表示该光源所发出的光,照射到粗糙表面时经过漫反射,所得到的光的强度(颜色)。
GL_SPECULAR表示该光源所发出的光,照射到光滑表面时经过镜面反射,所得到的光的强度(颜色)。
(2)GL_POSITION属性。
表示光源所在的位置。
由四个值(X, Y, Z, W)表示。
如果第四个值W为零,则表示该光源位于无限远处,前三个值表示了它所在的方向。
这种光源称为方向性光源,通常,太阳可以近似的被认为是方向性光源。
如果第四个值W不为零,则X/W, Y/W, Z/W表示了光源的位置。
这种光源称为位置性光源。
对于位置性光源,设置其位置与设置多边形顶点的方式相似,各种矩阵变换函数例如:glTranslate*、glRotate*等在这里也同样有效。
方向性光源在计算时比位置性光源快了不少,因此,在视觉效果允许的情况下,应该尽可能的使用方向性光源。
(3)GL_SPOT_DIRECTION、GL_SPOT_EXPONENT、GL_SPOT_CUTOFF属性。
表示将光源作为聚光灯使用(这些属性只对位置性光源有效)。
很多光源都是向四面八方发射光线,但有时候一些光源则是只向某个方向发射,比如手电筒,只向一个较小的角度发射光线。
GL_SPOT_DIRECTION属性有三个值,表示一个向量,即光源发射的方向。
GL_SPOT_EXPONENT属性只有一个值,表示聚光的程度,为零时表示光照范围内向各方向发射的光线强度相同,为正数时表示光照向中央集中,正对发射方向的位置受到更多光照,其它位置受到较少光照。
数值越大,聚光效果就越明显。
GL_SPOT_CUTOFF属性也只有一个值,表示一个角度,它是光源发射光线所覆盖角度的一半(见图2),其取值范围在0到90之间,也可以取180这个特殊值。
取值为180时表示光源发射光线覆盖360度,即不使用聚光灯,向全周围发射。
图2(4)GL_CONSTANT_ATTENUATION、GL_LINEAR_ATTENUATION、GL_QUADRATIC_ ATTENUATION属性。
这三个属性表示了光源所发出的光线的直线传播特性(这些属性只对位置性光源有效)。
现实生活中,光线的强度随着距离的增加而减弱,OpenGL把这个减弱的趋势抽象成函数:衰减因子 = 1 / (k1 + k2 * d + k3 * k3 * d)其中d表示距离,光线的初始强度乘以衰减因子,就得到对应距离的光线强度。
k1, k2, k3分别就是GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION,GL_QUADRATIC_ATTENUATION。
通过设置这三个常数,就可以控制光线在传播过程中的减弱趋势。
属性还真是不少。
当然了,如果是使用方向性光源,(3)(4)这两类属性就不会用到了,问题就变得简单明了。
四、控制材质材质与光源相似,也需要设置众多的属性。
不同的是,光源是通过glLight*函数来设置的,而材质则是通过glMaterial*函数来设置的。
glMaterial*函数有三个参数。
第一个参数表示指定哪一面的属性。
可以是GL_FRONT、GL_BACK或者GL_FRONT_AND_BACK。
分别表示设置“正面”“背面”的材质,或者两面同时设置。
(关于“正面”“背面”的内容需要参看前些课程的内容)第二、第三个参数与glLight*函数的第二、三个参数作用类似。
下面分别说明glMaterial*函数可以指定的材质属性。
(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属性。
(2)GL_SHININESS属性。
该属性只有一个值,称为“镜面指数”,取值范围是0到128。
该值越小,表示材质越粗糙,点光源发射的光线照射到上面,也可以产生较大的亮点。
该值越大,表示材质越类似于镜面,光源照射到上面后,产生较小的亮点。
(3)GL_EMISSION属性。
该属性由四个值组成,表示一种颜色。
OpenGL认为该材质本身就微微的向外发射光线,以至于眼睛感觉到它有这样的颜色,但这光线又比较微弱,以至于不会影响到其它物体的颜色。
(4)GL_COLOR_INDEXES属性。
该属性仅在颜色索引模式下使用,由于颜色索引模式下的光照比RGBA模式要复杂,并且使用范围较小,这里不做讨论。
五、选择光照模型这里所说的“光照模型”是OpenGL的术语,它相当于我们在前面提到的“光照环境”。
在OpenGL中,光照模型包括四个部分的内容:全局环境光线(即那些充分散射,无法分清究竟来自哪个光源的光线)的强度、观察点位置是在较近位置还是在无限远处、物体正面与背面是否分别计算光照、镜面颜色(即GL_SPECULAR属性所指定的颜色)的计算是否从其它光照计算中分离出来,并在纹理操作以后在进行应用。