OpenGL glLightfv 函数的应用以及光源的相关知识

首先介绍OpenGL的简单光照模型,它的反射光可以分为三个分量:环境反射光,漫反射光,镜面反射光。就是你要实现一个光照效果,需要设置这三个分量,三者之和达到你想要的光照效果。

1.环境光,简单来说就是环境中的光,似乎来自于各个方向

2.漫反射,来自一个方向,光它照射到物体上,则在各个方向上均匀地发散出去,不管视点在哪,物体都是一样亮。

3.镜面光,来自特定方向,并沿着另一方向反射出去。

glLightfv函数原型:void glLightfv(光源名, 类型, 赋值);

类型主要有四类:光源颜色---AMBIENT、DIFFUSE、SPECULAR和光源位置---POSITION

其中DIFFUSE的参数与光源颜色紧密,一般简单的光照模型只设置DIFFUSE就足够用了

GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);

下面是赋值的代码:

GLfloat light0_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};
GLfloat light0_specular[] = { 1.0, 0, 0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR,light0_specular);

设置光源位置

GLfloat light0_position[] = { 1.0, 1.0, 1.0, 0.0 };
 
glLightfv(GL_LIGHT0, GL_POSITION,light0_position);

开启光源 

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);

glEnable(GL_LIGHTING);表示启动光照的总开关 glEnable(GL_LIGHT0);//打开0号光源

glEnable(GL_DEPTH_TEST);//打开深度缓冲区,绘制3D图像时候使用

完整代码

 

 
#include "stdafx.h"
#include <GL/glut.h>
#include "math.h"
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,1.5 * (GLfloat)h / (GLfloat)w, -1.5,1.5);
	else
		glOrtho(-1.5* (GLfloat)w / (GLfloat)h, 1.5, -1.5,1.5, -1.5,1.5 );
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
}
 
void init ()
{
glClearColor(1.0,1.0,1.0,0.0);
glColor3f(1.0,1.0,0.0);
GLfloat light0_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};//红色点光源
GLfloat light0_specular[] = { 1.0, 0, 0, 1.0 };
GLfloat light0_position[] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR,light0_specular);
glLightfv(GL_LIGHT0, GL_POSITION,light0_position);
glShadeModel(GL_SMOOTH);//光滑着色,过渡色效果
glEnable(GL_LIGHTING);//启动光照,总开关
glEnable(GL_LIGHT0);//打开0号光源
glEnable(GL_DEPTH_TEST);
 
}
void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glutSolidTeapot(0.5);
	glFlush();
}
int main(int argc, char* argv[])
{
	glutInit(&argc,argv);
	glutInitWindowPosition(200,200);
    glutInitWindowSize(500,500);
	glutCreateWindow("001");
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMainLoop();
	return 0;
}

运行结果

 我们发现茶壶的颜色被设置的光照给覆盖了,本身的颜色(黄色)并没有显示出来。这里引入一个新的函数---颜色材质函数glEnable(GL_COLOR_MATERIAL); 它确保了打开灯光效果之后还能保留图形颜色。使用时候放在init函数里即可。

添加后茶壶效果如下

 

事实上光源才是所有光照效果的基础,没有光源一切都无从谈起。OpenGL中我们可以设置8个光源,其编号分别为GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7。就相当于现实生活中有8个太阳,但每个太阳的位置、方向及它发出的光线可以完全不同。因此,OpenGL中我们设置光源时,主要就是设置其颜色、位置、方向等性质。另外,OpenGL中任何一个光源都可以发出不同强度的环境光、散射光、镜面反射光,这几个方面综合起来就决定了光源的颜色。

我们通过glLightfv(光源编号,光源特性,参数数据)来设置光源。其中,光源编号可取GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7共8个值。光源特性主要可取GL_AMBIENT(设置光源的环境光属性,默认值(0,0,0,1))、GL_DIFFUSE(设置光源的散射光属性,默认值(1,1,1,1))、GL_SPECULAR(设置光源的镜面反射光属性,默认值(1,1,1,1))、GL_POSITION(设置光源的位置,默认值(0,0,1,0))。参数数据格式要求为数组形式,即数学上的向量形式。

下面一段代码,我们将一个光源的性质进行完整设置:

GLfloat Va[]={0.4,0.4,0.4,1};           //光源环境光强度数组  
GLfloat Vd[]={0.6,0.6,0.6,1};           //光源散射光强度数组  
GLfloat Vs[]={0.6,0.6,0.6,1};           //光源镜面反射光强度数组  
GLfloat Vp[]={1,1,1,1};             //光源位置数组  
glLightfv(GL_LIGHT0,GL_AMBIENT,Va); //设置0号光源的环境光属性  
glLightfv(GL_LIGHT0,GL_DIFFUSE,Vd); //设置0号光源的散射光属性  
glLightfv(GL_LIGHT0,GL_SPECULAR,Vs);    //设置0号光源的镜面反射光属性  
glLightfv(GL_LIGHT0,GL_POSITION,Vp);    //设置0号光源的位置属性  

光源的性质设置完毕,还要调用glEnable(GL_LIGHT0)来打开光源。就相当于你买回手电筒、装好电池(设置光源),但如果不打开开关(打开电源),手电筒是不起作用的。

另外,对于GL_POSITION,其位置数组(x,y,z,w)定义了光源在空间中的位置。但三维空间为什么需要4个量呢?事实上这里采用的是齐次坐标,当w≠0时,它表示光源处于空间中(x,y,z)处,这时的光源称为定点光源;当w=0时,根据齐次坐标的性质,它表示光源位于无穷远处,此时光源称为定向光源,其所有光线几乎是相互平等的,如太阳。其光线方向由点(x,y,z)指向(0,0,0)。

将第2章中的正方体的例子做以下修改。修改后的void __fastcall TForm1::OpenGL1 GLPaint(TObject *Sender)处的代码如下(其余位置不变):

void __fastcall TForm1::OpenGL1GLPaint(TObject *Sender)  
{  
  glEnable(GL_DEPTH_TEST);          //隐藏表面消除  
  glClear(GL_DEPTH_BUFFER_BIT); //清除窗口颜色  
 
  const GLfloat glfLightAmbient1[4] = {0.1, 0.1, 0.1, 1.0};  
  const GLfloat glfLightAmbient2[4] = {0.4, 0.4, 0.4, 1.0};  
  const GLfloat glfLightDiffuse1[4] = {0, 0.8, 0.8, 1.0};  
  const GLfloat glfLightDiffuse2[4] = {0.8, 0.8, 0.8, 1.0};  
  const GLfloat glfLightSpecular1[4] = {0, 0.8, 0.8, 1.0};  
  const GLfloat glfLightSpecular2[4] = {0.8, 0.8, 0.8, 1.0};  
  const GLfloat glPosition1[4]={0,0,1,0};  
  const GLfloat glPosition2[4]={0.6,0.6,-0.6,1};  
  glLightfv(GL_LIGHT0, GL_AMBIENT,  glfLightAmbient1);  
  glLightfv(GL_LIGHT0, GL_DIFFUSE,  glfLightDiffuse1);  
  glLightfv(GL_LIGHT0, GL_SPECULAR, glfLightSpecular1);  
  glLightfv(GL_LIGHT0,GL_POSITION,glPosition1);  
  glLightfv(GL_LIGHT1, GL_AMBIENT,  glfLightAmbient2);  
  glLightfv(GL_LIGHT1, GL_DIFFUSE,  glfLightDiffuse2);  
  glLightfv(GL_LIGHT1, GL_SPECULAR, glfLightSpecular2);  
  glLightfv(GL_LIGHT1,GL_POSITION,glPosition2);  
  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);//两面照亮  
      glEnable(GL_LIGHTING);//启用光照  
      glEnable(GL_LIGHT0);  
      glEnable(GL_LIGHT1);//打开光源  
      glEnable(GL_COLOR_MATERIAL);//启用颜色追踪  
      glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);  
//物体正面的材料环境颜色和散射颜色,追踪glColor所设置的颜色(比较拗口,
事实上就是让OpenGL根据glColor所设置的颜色自动设置物体的反射强度)  
 
  glShadeModel(GL_FLAT);//设置颜色填充模式  
   glBegin(GL_QUAD_STRIP) ;  
     glVertex3f(i,-i,i);  
     glVertex3f(i,-i,-i);  
     glColor3f(1,0,0);  
     glVertex3f(-i,-i,i);  
     glVertex3f(-i,-i,-i);  
     glColor3f(0,1,0);  
     glVertex3f(-i,i,i);  
     glVertex3f(-i,i,-i);  
     glColor3f(0,0,1);  
     glVertex3f(i,i,i);  
     glVertex3f(i,i,-i);  
     glColor3f(1,1,0);  
     glVertex3f(i,-i,i);  
     glVertex3f(i,-i,-i);  
   glEnd();  
   glBegin(GL_QUADS);  
     glVertex3f(i,-i,i);  
     glVertex3f(-i,-i,i);  
     glVertex3f(-i,i,i);  
     glColor3f(1,0,1);  
     glVertex3f(i,i,i);  
 
     glVertex3f(i,-i,-i);  
     glVertex3f(-i,-i,-i);  
     glVertex3f(-i,i,-i);  
     glColor3f(0,1,1);  
     glVertex3f(i,i,-i);  
   glEnd();  
 
      glDisable(GL_LIGHTING);//关闭光照  
      glDisable(GL_LIGHT0);//关闭0号光源  
      glDisable(GL_LIGHT1); //关闭1号光源  
}  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值