孙其功陪你学之——OpenGL 光照和材料属性

来源:互联网 发布:中兴商城下载软件 编辑:程序博客网 时间:2024/06/05 09:26

OpenGL 光照和材料属性 

转自: http://hsw625728.blog.163.com/blog/static/3957072820081151004846/

 

glLightfv是光源

glLightModelfv是材质

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);   //材质属性的镜面反射指数 
   glMaterialfv(GL_FRONT,GL_EMISSION,mat_emission);      //材质属性中的发射光 
   
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);      //指定光源位置
   glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);  //光源中的环境光强度 
   glLightfv(GL_LIGHT0,GL_DIFFUSE,white_light);  //光源中的散射光强度 
   glLightfv(GL_LIGHT0,GL_SPECULAR,white_light); //光源中的镜面反射光强度

 

 

首先是光照的设置,光照分为三类环境光散射光镜面光,根据此时的理解,记录下今天所掌握的知识,先设置3个数组后面会用到

GLfloat amb[] = {0.3f,0.3f,0.3f,1.0f};//环境光成分

GLfloat dif[] = {0.7f,0.7f,0.7f,1.0f};//散射光成分

GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};//镜面光成分

环境光是从物体的各个方向照射物体的,他产生的效果和关闭光照效果几乎相同,因为在关闭光照效果的时候,物体总是可见的并均匀着色,与他们的旋转和观察角度无关,若打开光照效果glEnable(GL_LIGHTING)而不指定环境光,这时默认的环境光是(0.2,0.2,0.2,1.0),这是非常微弱的光,画面上的物体会非常的暗淡,这时我们指定一个自己的第一个光源light0,先给他设置环境光glLightfv(GL_LIGHT0,GL_AMBIENT,amb),amb是开始定义的表示环境光成分的数组

散射光是一种有特定方向的光,在物体表面是均匀的反射的,也可以理解成漫反射光,和下面学习的经面光有些相似,若以散射光照射一个球体作为例子,正对着散射光方向的表面是亮的,背对着光线方向的表面是暗淡的,在光线掠过的侧面的亮度是介于两者之间的,这和在一个黑屋子里用手电筒照射一个篮球的效果很相似,这时给上面的光源light0指定一种散射光glLightfv(GL_LIGHT0,GL_DIFFUSE,dif),dif是开始定义的表示散射光成分的数组

最后是镜面光,这种光比较好理解,和上面的散射光一样,他也是有一定的方向,但在物体表面的反射是很强烈的,可以理解为镜面反射光,他会在物体边面形成一个亮点(光斑),在生活中强光照射在比较平整的表面就是这种效果,如在阳光照射下表面无锈迹的铁球,再给上面的光源light0加上镜面光成分,flLightfv(GL_LIGHT0,GL_SPECULAR,spe),spe是开始定义的表示镜面光成分的数组

在特定的光源设置好以后这时就可以启用这用个光源,glEnable(GL_LIGHT0);

以下就是设置并启用自定义光源的代码

glEnable(GL_LIGHTING);//启动光照效果

GLfloat amb[] = {0.3f,0.3f,0.3f,1.0f};//环境光成分

GLfloat dif[] = {0.7f,0.7f,0.7f,1.0f};//散射光成分

GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};//镜面光成分

 

glLightfv(GL_LIGHT0,GL_AMBIENT,amb); //添加环境光成分

glLightfv(GL_LIGHT0,GL_DIFFUSE,dif); //添加散射光成分

glLightfv(GL_LIGHT0,GL_SPECULAR,spe);//给自定义光源light0添加镜面光成分

 

glEnable(GL_LIGHT0);     //启用自定义的光源

 

光照定义完成后,还要定义物体的表面的材料属性,材料的属性对最后的效果影响也是巨大的,因为最终在屏幕上显示的效果是光源发出的光经过材料反射后才能最终确定的,材料的属性设置和光源的设置有些类似,用到的函数glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,amb)第一个参数指定了是哪个表面需要被渲染,第二个参数是哪个材料属性将要被设置,第三个参数是指定哪种颜色的光会被反射(用了上面的一个数组),一般情况下材料对环境光和对散射光的反射率是相同的,所以上面的参数用了GL_AMBIENT_AND_DIFFUSE

上面的光源设置中用到了镜面光,若此时在材料属性中不设置镜面反射效果,则上面的镜面光也就没什么作用,镜面反射的设置和光源的镜面光设置类似glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe),若绘制的物体想要有光泽那么这个设置是必须的(例如光滑的大理石表面),若绘制的物体的表面没有光泽那么这个属性就不用设置(例如粗糙的石板表面),在镜面反射设置后还有一个问题需要解决,那就是高强度的镜面光和强烈的镜面反射效果会导致物体将以几乎接近白色的效果出现,如若想要在物体表面形成一个亮斑,还需要一个函数glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,45);中间的一个参数是镜面指数,他指定了镜面反射加亮的大小和集中性,如果最后一个参数设置为0那表示不聚焦,也就是整个表面均匀加亮,若设置为128表示最大程度的聚焦,也就是光斑点最小的情况。

一下是材料属性设置的代码

glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,amb);//材料对环境光的反射情况

glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif);//散射光的反射情况

glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);//镜面光的反射情况

glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,45);//镜面光的聚焦情况

 

这样就可以渲染出比原来更为真实的三位物体,但还有一点不足,就是当物体的颜色经常发生变化时,那么必须每次进行材料反射属性的更改,将调用一次glMaterialfv(),那将是件很麻烦的工作,这里可以用到一个方法,也是以后最常用到的方法,叫做颜色追踪。若使用了这种方法,可以在以后的渲染中通过调用glColor来设置材料的属性,方法如下

glEnable(GL_COLOR_MATERIAL);         //启用颜色追踪

glColorMaterial(GL_FRONT_AND_BACK,FL_AMBIENT_AND_DIFFUSE); //正面和反面,环境光和散射光

设置好后,以后就可以通过调用glColor来设置材料的反射属性了。

以下是今天程序的完整代码 

 

#include "StdAfx.h"
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <glut.h>  //有时候为#include <gl/glut.h>
#include <math.h>
 

 

 

GLfloat position_x = -25.0f;

GLfloat position_y = 25.0f;

GLfloat change_x = 0.1f;

GLfloat change_y = 0.1f;

GLfloat Height = 100.0f;

GLfloat Width = 100.0f;

 

GLfloat temp = 1.0f ;

void TimeFunction(void)

{

glutPostRedisplay();

glutTimerFunc(33,TimeFunction,1);

 

}

void RenderScene(void)

{

static GLint angle_x = 0;

static GLint angle_y = 0;

static GLint angle_z = 0;

GLint temp_i,temp_j;

angle_x += 1;

angle_y += 2;

angle_z += 4;

 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

 glColor3f(0.0f,0.95f,0.24f);

 glMatrixMode(GL_MODELVIEW);

 glLoadIdentity();

 

 

glPushMatrix();

 glTranslatef(0.0f,0.0f,-50.0f);

 glRotatef(angle_x++,0.0f,1.0f,0.0f);

 glutSolidTorus(1,8,30,40);

 glColor3f(1.0f,0.0f,0.0f);

 glutSolidSphere(3.5f,40,40);

glPopMatrix();

 

glPushMatrix();

 glTranslatef(0.0f,0.0f,-50.0f);

    glPushMatrix();

 glTranslatef(-30.0f,10.0f,0.0f);

 glColor3f(1.0f,0.0f,0.0f);

 glutSolidSphere(3.5f,40,40);

    glPopMatrix();

 

    glPushMatrix();

 glTranslatef(-30.0f,25.0f,0.0f);

 glColor3f(1.0f,0.0f,0.0f);

 glutSolidSphere(3.5f,40,40);

    glPopMatrix();

 

glPopMatrix();

glPushMatrix();

 glColor3f(1.0f,1.0f,0.0f);

 glTranslatef(30.0f,0.0f,-50.0f);

 glutSolidSphere(5.0f,40,40);

glPopMatrix();

 //glutSolidSphere(12.0f,40,40);

 //glutSolidTeapot(12.0f);

//以下是地面的绘制

//底色

 

glColor3f(1.0f,1.0f,1.0f);

glBegin(GL_TRIANGLE_FAN);

    glVertex3f(-1500.0f,-30.5f,0.0f);

    glVertex3f(-1500.0f,-30.5f,-2500.0f);

    glVertex3f(1500.0f,-30.5f,-2500.0f);

    glVertex3f(1500.0f,-30.5f,0.0f);

glEnd();

 

 glutSwapBuffers();

}

void SetupRC(void)

{

 GLfloat amb[] = {0.4f,0.4f,0.4f,1.0f};

 GLfloat dif[] = {6.0f,6.0f,6.0f,1.0f};

 GLfloat spe[] = {1.0f,1.0f,1.0f,1.0f};

 GLfloat pos[] = {-50.0f,50.0f,100.0f,1.0f};

 glClearColor(0.0f,0.0f,0.0f,1.0f);

 glEnable(GL_DEPTH_TEST);

 //glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);

 glEnable(GL_LIGHTING);

 glLightfv(GL_LIGHT0,GL_AMBIENT,amb);

 //glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);

 glLightfv(GL_LIGHT0,GL_SPECULAR,spe);

 glLightfv(GL_LIGHT0,GL_POSITION,pos);

//glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);

 glEnable(GL_LIGHT0);

 

 glEnable(GL_COLOR_MATERIAL);

 glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

 glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);

 glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,128);

}

 

void ChangeSize(GLsizei w,GLsizei h)

{

GLfloat aspectRatio;

if(h == 0)

 h = 1;

glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

temp = aspectRatio = (GLfloat)w/(GLfloat)h;

    if(w <= h)

 //glOrtho(-100.0,100.0,-100/aspectRatio,100.0/aspectRatio,0.0,100.0);

 gluPerspective(60,temp,0.1f,1000.0f);

    else

 //glOrtho(-100.0*aspectRatio,100.0*aspectRatio,-100.0,100.0,0.0,100.0);

 gluPerspective(60,temp,0.1f,1000.0f);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

 

int main(int argc ,char *argv[])

{

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

 

glutCreateWindow("Color Material");

glutDisplayFunc(RenderScene);

glutReshapeFunc(ChangeSize);

glutTimerFunc(33,TimeFunction,1);

SetupRC();

glutMainLoop();

 

return 0;

}

执行结果:

原创粉丝点击