OpenGL 光照和材质

OpenGL 光照和材质

前言:很难受呀,一天又过去了,没有达到预期的进度,等下写完这篇博客,抓紧研究鼠标实现轨迹球!
长路漫漫啊……

注:此篇文章建立在MFC环境搭建完成后


1.渲染处理

在OpenGL中,可以定义顶点的颜色,但如何定义线段的颜色,如何定义平面的颜色,这就需要OpenGL通过各个顶点的颜色采用两种不同的渲染处理方法。

明暗渲染处理:void glShadeMode(GLenum mode),直译为阴影模式。
GL_SMOOTH: 平滑地采用光滑变化的明暗渲染方式;
GL_FLAT:采用第一个顶点的颜色绘制一个图元面,每增加一个图元面颜色重新定义;

可以看一下两者的区别:右图glShadeModel(GL_FLAT) ;左图glShadeModel(GL_SMOOTH);



2.光照

简单来说,物体显示的光是由三类光合成的:
泛光:通常称为环境光;
漫反射光:光照射到物体上反射出的光;
镜面反射光:也叫高光,物体某一点比较亮的区域;


启动和关闭光照:
启动:glEnable(GL_LIGHTING);         关闭:glDisable(GL_LIGHTING);

启动与关闭具体某一盏灯:
启动:glEnable(GL_LIGHTi);             关闭:glDisable(GL_LIGHTi);        i为非负整数。
例如:
glEnable(GL_LIGHTING);   //启动光照
glEnable(GL_LIGHT0);       //启用第一盏灯

OpenGL通过函数定义光照属性:
void glLightfv(GLenum light,GLenum pname,const GLfloat *p);
第一参数为灯的序号,第二个参数是状态变量,第三个参数设置光的色彩,使用数组地址填充;
附上一张第二个参数对应表:


附上我今天使用光照和材质的设置:
void CStepinGLView::LightM(void)
{
	glClearColor(1.0,1.0,1.0,0.0);
	//设置光照
	const GLfloat light_ambient[]  = { 0.0f, 0.0f, 0.0f, 1.0f };
	const GLfloat light_diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
	const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	const GLfloat light_position[] = { 5.0f, 5.0f, 5.0f, 0.0f };

	const GLfloat mat_ambient[]    = { 0.7f, 0.7f, 0.7f, 1.0f };
	const GLfloat mat_diffuse[]    = { 0.8f, 0.8f, 0.8f, 1.0f };
	const GLfloat mat_specular[]   = { 1.0f, 1.0f, 1.0f, 1.0f };
	const GLfloat high_shininess[] = { 100.0f };


	glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);

	glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
	glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);

}

函数定义光的位置采用数组齐次坐标(x,y,z,w);如果w为0,则该光源为定向光源,照射方向是原点指向(-x,-y,-z),位置在无穷远;如果w不为0,OpenGL认为是点光源,光源位置(x/w,y/w,z/w)。

关于光照的衰减方式和聚光的定义,这里就不探讨了。


3.物体的材质

物体材质的定义同样是相对光线的,也就是如果定义了光照,OpenGL就默认材质;如果定义了材质,没有光线启动,材质也不会 启动;
材质分为两种:一种是完全被动的,也就是被动地接受或只是材质与光线的作用;
二是材质色彩占主导,结合材质变换和光线影响;

启用和关闭材质:
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_COLOR_MATERIAL);

定义材质属性函数:
void glMateriafv(GLenum face,GLenum pname,const GLfloat *p);
第一个参数face为状态变量:GL_FRONT:材质的前面;GL_BACK:材质的后面;GL_FRONT_AND_BACK:材质的双面;
第二个参数pname为状态变量:GL_AMBIENT:设置材质反射环境光的色彩;GL_DIFFUSE:设置材质反射漫反射光色彩;GL_AMBIENT_AND_DIFFUSE:设置反射环境光和漫反射光色彩;GL_SPECULAR:设置材质反射镜面光色彩;

OpenGL还通过第二个参数定义材质的其他属性:
GL_SHININESS:设置光强度,范围[0.0,128.0],数值越小,反射越强,物体高光越明显;
GL_EMISSION:设置辐射光的色彩,缺省值(0.0,0.0,0.0,1.0)。

注:辐射光是材质发出的光,和环境光一样不会衰减,并且不等同于光源,是可见的。
定义辐射光材质:
GLfloat mEmi[4] = {0.3f,0.3f,0.3f,1.0f};
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,mEmi);

4.法线

OpenGL在采用光照计算时,将用到前面讲到的右手定则定义的法线,但是对于一个复杂的曲面来说,在采用光照时,最好定义出法线,这样有利于光照的计算。


启用和关闭法线:
glEnable(GL_NORMALIZE);
glDisabel(GL_NORMALIZE);
法线定义:
glNormal3f(x,y,z);


5.全局的光照模型
这个我看不太懂,就先附上图片,以后用到再进行讨论;


对于光照和材质就先说那么多吧,附上我写的一段代码:
void CStepinGLView::DrawScene(void)
{
	//移动物体到显示区
	glTranslatef(0.0f,0.0f,-7.0f);
	
	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
	
	//视角变换  
	glMatrixMode(GL_MODELVIEW);  
	glLoadIdentity(); 
	gluLookAt(0.0,3.0,7.0, 0.0,0.0,0.0, 0.0,1.0,0.0);/*前三个参数是眼睛的位置,中间三个参数是物体所在的位置,后面三个参数表示向量,头顶朝上的方向*/  
	//矩阵堆栈函数,和glPopMatrix()相对应  
	//glColor3f(102,139,139);
	
	
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_NORMALIZE);
	glEnable(GL_COLOR_MATERIAL);

	glPushMatrix();
	LightM();
	glPopMatrix();

	glPushMatrix();
	glColor3f(0.5f, 0.25f, 0.0f);
	glRotatef(rtri,0.0f,0.1f,0.0f);
	//DrawOccluder();
	glScalef(0.5f,0.5f,0.5f);
	glShadeModel(GL_SMOOTH);
	glutSolidTeapot(0.5f);
	glPopMatrix();

	glPushMatrix();
	glRotated(-65,1.0,0.0,0.0);
	DrawWater();
	glPopMatrix();
	
	glDisable(GL_LIGHTING);
	glDisable(GL_COLOR_MATERIAL);
}
程序运行截图:



PS:写到最后,发现忘了讲解gluLookAt()函数了,下篇博文见吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值