OPENGL的光影效果(转)

原创 2007年10月08日 11:30:00

为什么3D作图常常能产生另人震惊的效果?因为利用3D作图,你可以生成一些 现实中难得实现的真实的感受。特别是一些特殊的光影效果。
其实光源前面已经讲的很全面了,只是缺少一些专门的例子。这里我们来稍微 加深一下认识,我们将在例子中看到一个地方的光源对不同物体发出不同的光
这在现实中是少见的吧?

1.双面光照:
void glLightModeli(LIGHT_MODEL_TWO_SIDE,GL_TRUE);
光照计算通常是对多边形进行的。一般设置光照的条件总是对正面的多边形,而不考虑背面,但是如果考虑一个物体被劈开,光源的个数又会影响可见性,那么有必要对多边形双面都进行计算,这就是上面函数的功能;取消这一功能只须把第三个参数改为GL_FALSE。

2.聚光源
定义聚光源的函数仍是利用glLightfv(),需要设定的参数包括:光源位置、光源发散半角和光源聚光方向。

具体实现可以看下面例子:
//////////////////////////////////////////////////////////
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"

void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);

void initlights(void)
{
//定义物体材质特性的数值
GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};
GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};
GLfloat mat_specular[]={1.0,1.0,1.0,1.0};
GLfloat mat_shininess[]={80.0};

//定义第0个光源的属性(这是平行的环境光,没有聚光效果)
GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};
GLfloat light0_position[]={1.0,1.0,1.0,0.0};
//定义第一个光源的属性(聚光灯一)
GLfloat light1_ambient[]={0.2,0.2,0.2,1.0};
GLfloat light1_diffuse[]={1.0,0.0,0.0,1.0};
GLfloat light1_specular[]={1.0,0.6,0.6,1.0};
GLfloat light1_position[]={-3.0,-3.0,3.0,1.0};
GLfloat spot_direction[]={1.0,1.0,-1.0};

//定义第二个光源的属性(聚光灯二)
GLfloat light2_ambient[]={0.2,0.6,0.2,1.0};
GLfloat light2_diffuse[]={0.0,1.0,0.0,1.0};
GLfloat light2_specular[]={0.0,1.0,0.0,1.0};
GLfloat light2_position[]={-3.0,-3.0,3.0,1.0};
GLfloat spot2_direction[]={1.0,1.0,-1.0};
//!!!我们看到第一和第二个聚光源除了在颜色的定义上一个偏红,一个偏绿
//其他没有任何不同,所以如果象我们后面作的,对一个物体开启一个光源,对
//另一个物体开启另一个光源,就会产生一个点光源对不同物体发出不同光的效果

//将前面的属性定义加以应用
glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,light0_position);

glLightfv(GL_LIGHT1,GL_AMBIENT,light1_ambient);
glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse);
glLightfv(GL_LIGHT1,GL_SPECULAR,light1_specular);
glLightfv(GL_LIGHT1,GL_POSITION,light1_position);
//定义聚光灯发散角
glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,30.0);
//定义聚光灯发射方向的向量
glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,spot_direction);

glLightfv(GL_LIGHT2,GL_AMBIENT,light2_ambient);
glLightfv(GL_LIGHT2,GL_DIFFUSE,light2_diffuse);
glLightfv(GL_LIGHT2,GL_SPECULAR,light2_specular);
glLightfv(GL_LIGHT2,GL_POSITION,light2_position);

glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,30.0);
glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,spot2_direction);

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,mat_shininess);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);

}

void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
initlights();
// glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{

glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if(w<=h)
glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);
else
glOrtho(-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void CALLBACK display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//首先标出聚光源一、二的位置(同一位置)
glPushMatrix();
glTranslated(-3.0,-3.0,3.0);
glDisable(GL_LIGHTING);
glColor3f(1.0,0.0,0.0);
auxWireCube(0.1);
glEnable(GL_LIGHTING);
glPopMatrix();

//关掉第二个光源,只启用第一个光源(红),绘制球体一
glPushMatrix();
glDisable(GL_LIGHT2);
glTranslated(0.0,2.0,0.0);
auxSolidSphere(2.0);
glPopMatrix();

//关掉第一个光源,只启用第二个光源(绿),绘制球体二
glPushMatrix();
glDisable(GL_LIGHT1);
glEnable(GL_LIGHT2);
glTranslated(0.0,-2.0,0.0);
auxSolidSphere(2.0);
glPopMatrix();

glFlush();
}
void main(void)
{
myinit();

auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
///////////////////////////////////////////////////////////////
一个现实中难以见到的情景出现了。还不快试试?

结束光源之前,再给出一个光源移动的例子,其中用到了鼠标消息的响应,实现非常简单,以OPENGL的辅助库提供的方式调用一个CALLBACK函数即可,和以前讲的响应键盘输入的方法完全一样。
//////////////////////////////////////////////////////////////
//sample.cpp
#include "glos.h"
#include
#include
#include "windows.h"
void myinit(void);
void CALLBACK display(void);
void CALLBACK reshape(GLsizei w,GLsizei h);

//控制光源移动的变量
static int step=0;

//鼠标响应的CALLBACK函数
void CALLBACK movelight(AUX_EVENTREC *event)
{
step=(step+15)%360;
}

void initlights(void)
{
GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};
GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};
GLfloat mat_specular[]={1.0,1.0,1.0,1.0};
GLfloat mat_shininess[]={80.0};

GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};
GLfloat light0_ambient[]={0.2,0.5,0.5,1.0};

 

glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);
glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient);

 

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,mat_shininess);

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

}

void myinit(void)
{

auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
auxInitPosition(0,0,500,500);
auxInitWindow("sample1");
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);

glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
initlights();
// glShadeModel(GL_FLAT);
}

void CALLBACK reshape(GLsizei w,GLsizei h)
{

glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

if(w<=h)
glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0);
else
glOrtho(-5.0*(GLfloat)h/(GLfloat)w,
5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}


void CALLBACK display(void)
{
GLfloat position[]={0.0,0.0,1.5,1.0};

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glPushMatrix();
glTranslatef(0.0,0.0,-5.0);
glPushMatrix();

//光源的位置只由旋转变量step决定,每按下鼠标左键一下,step的值便会改变
//导致光源位置的改变
glRotated((GLdouble)step,-1.0,1.0,1.0);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glTranslated(0.0,0.0,1.5);

glDisable(GL_LIGHTING);
glColor3f(1.0,1.0,0.0);
auxWireSphere(0.25);
glEnable(GL_LIGHTING);

glPopMatrix();
auxSolidTorus(0.5,2.5);
glPopMatrix();

glFlush();


}
void main(void)
{
myinit();

auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,movelight);
auxReshapeFunc(reshape);
auxMainLoop(display);
}
//end of sample
/////////////////////////////////////////////////////////////
在例子中,黄色的小球表示当前光源的位置,它的旋转导致了环状体表面受光照部分的光影的变化,每按下鼠标左键一下,光源就会作响应的旋转。
 

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

事实上光源才是所有光照效果的基础,没有光源一切都无从谈起。OpenGL中我们可以设置8个光源,其编号分别为GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7。就相当于现实生活中有8个太阳...
  • chy19911123
  • chy19911123
  • 2015年06月08日 15:19
  • 3312

《高效学习OpenGL》 之 创建光源 glLightfv()

1.创建光源 void glLightfv (GLenum light, GLenum pname, const GLfloat *params); //创建指定的光源,light可以是GL_L...
  • huangbangqing12
  • huangbangqing12
  • 2014年02月19日 15:39
  • 6864

openGL 光照的学习

小狼学习原创,欢迎批评指正 先上代码
  • wolf96
  • wolf96
  • 2014年07月28日 00:25
  • 1409

开源项目之C++界面库 GLUI

GLUI是一个C++界面库,它提供了buttons, checkboxes, radio buttons, 等常用控件,以及OPENGL支持。GLUI界面系统依赖于GLUT来处理窗口、和鼠标管理等,而...
  • banketree
  • banketree
  • 2012年09月12日 14:56
  • 8661

OpenGL学习笔记(12)基本光照

比较这两个球 在现实生活中,比如一个表面是白色的球体,假设背景是黑色,然后没有任何灯光的照射那么就如右侧的圆一般,但这在有点不可能.现实中我们看到的都是左侧这样带有光照的球体,所以右侧的形状只能...
  • zcj331
  • zcj331
  • 2014年04月11日 13:29
  • 1231

OpenGL: 光源

代码如下:#define GLUT_DISABLE_ATEXIT_HACK #include "gl/glut.h" #pragma comment(lib, "glut32.lib") //显...
  • Augusdi
  • Augusdi
  • 2014年03月05日 09:45
  • 8107

开源项目之C++界面库 GLUI

GLUI是一个C++界面库,它提供了buttons, checkboxes, radio buttons, 等常用控件,以及OPENGL支持。GLUI界面系统依赖于GLUT来处理窗口、和鼠标管理等,而...
  • u013939659
  • u013939659
  • 2014年04月20日 12:19
  • 615

ARToolkit在VS2010(Win7 64位)下的配置及第一个开发程序的编译与运行

学习ARToolkit已经快一个月了,刚刚接触时只是按照官网教程中的步骤一步一步的学习,其中遇到了许多问题,如OpenGL在64位Win7下的配置问题、ARtoolkit在64位Win7下的配置问题、...
  • u012273127
  • u012273127
  • 2017年12月18日 17:43
  • 108

openGL的光照与材料(一)

真实感图形绘制是计算机图形学的一个重要组成部分,它综合利用数学、物理学、计算机科学和其它科学知识在计算机图形设备上生成象彩色照片那样的具有真实感的图形。一般说来,用计算机在图形设备上生成真实感图形必须...
  • chenxiao88957478
  • chenxiao88957478
  • 2016年02月29日 10:35
  • 1110

《高效学习OpenGL》 之 创建光源 glLightfv()

1.创建光源 void glLightfv (GLenum light, GLenum pname, const GLfloat *params); //创建指定的光源,light可以是GL_L...
  • huangbangqing12
  • huangbangqing12
  • 2014年02月19日 15:39
  • 6864
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OPENGL的光影效果(转)
举报原因:
原因补充:

(最多只允许输入30个字)