第五章_OpenGL光照与材质(二)

第五章_OpenGL光照与材质(二)
第五章_OpenGL光照与材质(二)

第五章光照与材质

5.8 全局环境光

每个光源可以有自己的环境光,但也可以有不来自于任何光源的环境光,指定环境光的方法是:

利用参数GL_LIGHT_MODEL_AMBIENT来调用函数glLightModel*()。

如:

float model_ambient[] = { 0.2 , 0.2 , 0.2 , 1.0 };

glLightModelfv(GL_LIGHT_MODEL_AMBIENT , model_ambient ) ;

上述代码为场景中的物体提供了软弱的白色环境光,所以即使场景中没有任何光源,也可以看到场景中的物体。

【综合示例EP5-5】场景中绘制一组静物模型,然后加入一个简单的光照,先使用光源自己的环境光,再统一使用全局环境光。

代码如下:

#include "stdafx.h"

int nAngleY=0; // 沿Y轴旋转的角度

int nAngleX=0; // 沿X轴旋转的角度

int nAngleZ=0; // 沿Z轴旋转的角度

void CALLBACK ClockwiseRotateByX()

{

nAngleX--;

}

void CALLBACK CounterClockwiseRotateByX()

{

nAngleX++;

}

void CALLBACK ClockwiseRotateByZ()

{

nAngleZ--;

}

void CALLBACK CounterClockwiseRotateByZ()

{

nAngleZ++;

}

void CALLBACK ClockwiseRotateByY()

nAngleY--;

}

void CALLBACK CounterClockwiseRotateByY()

{

nAngleY++;

}

void myinit (void)

{

/* 将背景清为白色*/

glClearColor (0.0, 0.0,0.0, 1.0);

glShadeModel (GL_SMOOTH);

GLfloat ambient[] = { 0.5, 0.0, 0.0, 1.0 };

GLfloat specular[] = { 1.0, 1.0, 0.0, 1.0 };

GLfloat diffuse[] = { 0.5, 0.5, 0.5, 1.0 };

GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

GLfloat model_ambient[] = { 0.3, 0.0, 0.3, 1.0 };

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat mat_shininess[] = { 128.0 };

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

glLightfv(GL_LIGHT1, GL_POSITION, light_position);

//glLightfv (GL_LIGHT1, GL_AMBIENT, ambient);

glLightfv (GL_LIGHT1, GL_SPECULAR, specular);

glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);

// 指定全局环境光

glLightModelfv(GL_LIGHT_MODEL_AMBIENT,model_ambient);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT1);

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST);

glEnable(GL_AUTO_NORMAL);

glEnable(GL_NORMALIZE);

void CALLBACK reshape(GLsizei w, GLsizei h)

{

if (!h) return;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho (-500.0, 500.0, -500.0*(GLfloat)h/(GLfloat)w,

500.0*(GLfloat)h/(GLfloat)w, -500, 500);

else

glOrtho (-500.0*(GLfloat)w/(GLfloat)h,

500.0*(GLfloat)w/(GLfloat)h, -500.0, 500.0, -500, 500);

glMatrixMode(GL_MODELVIEW);

}

void CALLBACK display(void)

{

glLoadIdentity();

glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除背景

glRotated(nAngleX,1,0,0);

glRotated(nAngleY,0,1,0);

glRotated(nAngleZ,0,0,1);

glLineStipple(1, 0x3F07); // 指定点划格式

glEnable(GL_LINE_STIPPLE); // 进入点划模式

glBegin(GL_LINES);

// X轴:红

glColor3f (1.0, 0, 0);

glVertex3d(-490,0,0);

glVertex3d(490,0,0);

// Y轴:绿

glColor3f (0.0, 1.0, 0);

glVertex3d(0,-490,0);

glVertex3d(0,490,0);

// Z轴:蓝

glColor3f (0.0, 0.0, 1);

glVertex3d(0,0,-490);

glVertex3d(0,0,490);

glEnd();

glDisable(GL_LINE_STIPPLE);//离开点划模式

glColor3f (1.0, 0.0, 0);

glPushMatrix(); // 车体

glTranslatef(0,210,0);

auxSolidBox(600, 20, 400);

glPopMatrix();

glPushMatrix(); // 左前腿

glTranslatef(-260,100,180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 左后腿

glTranslatef(-260,100,-180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 右前腿

glTranslatef(260,100,180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 右后腿

glTranslatef(260,100,-180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 球

glTranslatef(-200,260,0);

auxSolidSphere(40);

glPopMatrix();

glPushMatrix(); // 八面体

glTranslatef(-200,260,160);

auxSolidOctahedron(40);

glPopMatrix();

glPushMatrix(); // 圆锥体

glTranslatef(-60,220,120);

glRotatef(-90,1,0,0);

auxSolidCone(60, 100);

glPopMatrix();

glPushMatrix(); //

glTranslatef(60,270,0);

glRotatef(40,0,1,0);

auxSolidTeapot(70);

glPopMatrix();

glPushMatrix(); //

glTranslatef(240,360,0);

auxSolidCylinder(40,140);

glPopMatrix();

auxSwapBuffers();

}

int _tmain(int argc, _TCHAR* argv[])

{

auxInitDisplayMode (AUX_DOUBLE | AUX_RGBA);

auxInitPosition (0, 0, 1000, 700);

auxInitWindow ("全局环境光");

myinit ();

auxKeyFunc (AUX_LEFT, ClockwiseRotateByY);

auxKeyFunc (AUX_RIGHT, CounterClockwiseRotateByY);

auxKeyFunc (AUX_UP, ClockwiseRotateByX);

auxKeyFunc (AUX_DOWN, CounterClockwiseRotateByX);

auxKeyFunc (AUX_D, ClockwiseRotateByZ);

auxKeyFunc (AUX_d, ClockwiseRotateByZ);

auxKeyFunc (AUX_U, CounterClockwiseRotateByZ);

auxKeyFunc (AUX_u, CounterClockwiseRotateByZ);

auxReshapeFunc(reshape);//回调函数

auxMainLoop(display);

return 0;

}

5.9 近视点和无穷远视点

在无穷远点的情况下,场景中所有顶点到视点的方向都相同。采用近视点时(local viewpoint),结果的真实感会更强,但需计算每个顶点的方向,因此总体性能将下降。

默认情况下,认为视点位于无穷远处,位置将影响镜面反射区计算,也就是说,顶点的镜面反射亮度取决于该顶点的法线、顶点相对于光源的方向和顶点相对于视点的方向。指定方法是:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER , GL_TRUE) ;

上述代码把视点放在坐标系的(0 ,0 ,0 )处,若把视点放到无穷远处,则执行如下代码

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER , GL_FALSE) ;

上述代码可在EP5-5中实现。

【综合示例EP5-6】场景中绘制一组静物模型,使用透视投影实现。

把实验五中的投影方式,由平行投影改为透视投影。转动场景时,物体显示会出现不正常。其中一个关键是要加入面剔除功能,第二个关键是对于茶壶而言,其面的定义是按顺时针的,这与一般物体的定义不同。下面的关键代码已用粗体标出。

#include "stdafx.h"

int nAngleY=0; // 沿Y轴旋转的角度

int nAngleX=0; // 沿X轴旋转的角度

int nAngleZ=0; // 沿Z轴旋转的角度

void CALLBACK ClockwiseRotateByX()

{

nAngleX--;

}

void CALLBACK CounterClockwiseRotateByX()

{

nAngleX++;

}

void CALLBACK ClockwiseRotateByZ()

{

nAngleZ--;

}

void CALLBACK CounterClockwiseRotateByZ()

{

nAngleZ++;

}

void CALLBACK ClockwiseRotateByY()

{

nAngleY--;

}

void CALLBACK CounterClockwiseRotateByY()

{

nAngleY++;

}

void myinit (void)

{

/* 将背景清为白色*/

glClearColor (0.0, 0.0,0.0, 1.0);

glClearDepth(1.0f); // 深度范围在【,】之间

glShadeModel (GL_SMOOTH);

// 光源属性值

GLfloat ambient[] = { 0.5, 0.0, 0.0, 1.0 };

GLfloat specular[] = { 1.0, 1.0, 0.0, 1.0 };

GLfloat diffuse[] = { 0.5, 0.5, 0.5, 1.0 };

GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

// 材质属性值

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat mat_shininess[] = { 128.0 };

// 设置材质

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

// 设置光源

glLightfv(GL_LIGHT1, GL_POSITION, light_position);

glLightfv (GL_LIGHT1, GL_AMBIENT, ambient);

glLightfv (GL_LIGHT1, GL_SPECULAR, specular);

glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT1);

// 启动深度测试

glEnable(GL_DEPTH_TEST);

glDepthFunc(GL_LEQUAL);

// 启动自动法线

glEnable(GL_AUTO_NORMAL);

glEnable(GL_NORMALIZE);

// 启动面剔除功能

glEnable(GL_CULL_FACE); // 不渲染一些面的功能启动

glFrontFace(GL_CCW); // 指定正面的方向

glCullFace(GL_BACK); // 不渲染背面

}

void CALLBACK reshape(GLsizei w, GLsizei h)

{

if (!h) return;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluPerspective(60.0,w/h,1.0f,2000.0f);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void CALLBACK display(void)

{

glLoadIdentity();

glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除背景

glTranslatef(0,0,-1200);

glRotated(nAngleX,1,0,0);

glRotated(nAngleY,0,1,0);

glRotated(nAngleZ,0,0,1);

glLineStipple(1, 0x3F07); // 指定点划格式

glEnable(GL_LINE_STIPPLE); // 进入点划模式

glBegin(GL_LINES);

// X轴:红

glColor3f (1.0, 0, 0);

glVertex3d(-490,0,0);

glVertex3d(490,0,0);

// Y轴:绿

glColor3f (0.0, 1.0, 0);

glVertex3d(0,-490,0);

glVertex3d(0,490,0);

// Z轴:蓝

glColor3f (0.0, 0.0, 1);

glVertex3d(0,0,-490);

glVertex3d(0,0,490);

glEnd();

glDisable(GL_LINE_STIPPLE);//离开点划模式glFrontFace(GL_CCW);

glColor3f (1.0, 0.0, 0);

glPushMatrix(); // 车体

glTranslatef(0,210,0);

auxSolidBox(600, 20, 400);

glPopMatrix();

glPushMatrix(); // 左前腿

glTranslatef(-260,100,180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 左后腿

glTranslatef(-260,100,-180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 右前腿

glTranslatef(260,100,180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 右后腿

glTranslatef(260,100,-180);

auxSolidBox(25, 200, 25);

glPopMatrix();

glPushMatrix(); // 球

glTranslatef(-200,360,0);

auxSolidSphere(40);

glPopMatrix();

glPushMatrix(); // 八面体

glTranslatef(-200,360,160);

auxSolidOctahedron(40);

glPopMatrix();

glPushMatrix(); // 圆锥体

glTranslatef(-60,300,120);

glRotatef(-90,1,0,0);

auxSolidCone(60, 100);

glPopMatrix();

glFrontFace(GL_CW);

glPushMatrix(); //

glTranslatef(60,300,0);

glRotatef(40,0,1,0);

auxSolidTeapot(70);

glPopMatrix();

glFrontFace(GL_CCW);

glPushMatrix(); //

glTranslatef(240,362,0);

auxSolidCylinder(40,140);

glPopMatrix();

auxSwapBuffers();

}

int _tmain(int argc, _TCHAR* argv[])

{

auxInitDisplayMode (AUX_DOUBLE | AUX_RGBA|AUX_DEPTH);

auxInitPosition (0, 0, 1000, 700);

auxInitWindow ("透视投影下的光照");

myinit ();

auxKeyFunc (AUX_LEFT, ClockwiseRotateByY);

auxKeyFunc (AUX_RIGHT, CounterClockwiseRotateByY);

auxKeyFunc (AUX_UP, ClockwiseRotateByX);

auxKeyFunc (AUX_DOWN, CounterClockwiseRotateByX);

auxKeyFunc (AUX_D, ClockwiseRotateByZ);

auxKeyFunc (AUX_d, ClockwiseRotateByZ);

auxKeyFunc (AUX_U, CounterClockwiseRotateByZ);

auxKeyFunc (AUX_u, CounterClockwiseRotateByZ);

auxReshapeFunc(reshape);//回调函数

auxMainLoop(display);

return 0;

}

5.10材质

OpenGL用材料对光的红、绿、蓝三原色的反射率来近似定义材料的颜色。象光源一样,材料颜色也分成环境、漫反射和镜面反射成分,它们决定了材料对环境光、漫反射光和镜面反射光的反射程度(或者说成反射系数与前面的理论对应)。

在进行光照计算时,材料对环境光的反射率与每个进入光源的环境光相乘,对漫反射光的反射率与每个进入光源的漫反射光相乘,对镜面光的反射率与每个进入光源的镜面反射光相乘。对环境光与漫反射光的反射程度决定了材料的颜色,对镜面反射光的反射率通常是白色或灰色。镜面反射高光最亮的地方将变成具有光源镜面光强度的颜色。例如一个光亮的红色塑料球,球的大部分表现为红色,光亮的高光将是白色的。

5.10.1 材质RGB值和光源RGB值的关系

对于光源,R、G、B值等于R、G、B对其最大强度的百分比。若光源颜色的R、G、B值都是1.0,则是最强的白光;若值变为0.5,颜色仍为白色,但强度为原来的一半,于是表现为灰色;若R=G=1.0,B=0.0,则光源为黄色。

对于材质,R、G、B值为材质对光的R、G、B成分的反射率。比如,一种材质的R=1.0、G=0.5、B=0.0,则材质反射全部的红色成分,一半的绿色成分,不反射蓝色成分。也就是说,若OpenGL的光源颜色为(LR、LG、LB),材质颜色为(MR、MG、MB),那么,在忽略所有其他反射效果的情况下,最终到达眼睛的光的颜色为(LR*MR、LG*MG、LB*MB)。

对于两束光,相应的值分别为(R1、G1、B1)和(R2、G2、B2),则OpenGL将各个颜色成分相加,得到(R1+R2、G1+G2、B1+B2),若任一成分的和值大于1(超出了设备所能显示的亮度)则约简到1.0。

5.10.2 材质定义

材质的定义与光源的定义类似。其函数为:

void glMaterial{if}[v](GLenum face,GLenum pname,TYPE param);

定义光照计算中用到的当前材质。face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,它表明当前材质应该应用到物体的哪一个面上;pname说明一个特定的材质;param是材质的具体数值,若函数为向量形式,则param是一组值的指针,反之为参数值本身。非向量形式仅用于设置GL_SHINESS。pname参数值具体内容见表5-2。另外,参数GL_AMBIENT_AND_DIFFUSE表示可以用相同的RGB值设置环境光颜色和漫反射光颜色。GL_SHINESS值介于[0,128]之间,值越大,光斑越小,越集中。

表5-2 材质参数介绍

【综合示例EP5-7】材质的综合示例。

#include"stdafx.h"

int nAngleY=0; // 沿Y轴旋转的角度int nAngleX=0; // 沿X轴旋转的角度int nAngleZ=0; // 沿Z轴旋转的角度

void CALLBACK ClockwiseRotateByX()

{

nAngleX--;

}

void CALLBACK CounterClockwiseRotateByX() {

nAngleX++;

}

void CALLBACK ClockwiseRotateByZ()

{

nAngleZ--;

}

void CALLBACK CounterClockwiseRotateByZ() {

nAngleZ++;

}

void CALLBACK ClockwiseRotateByY()

{

nAngleY--;

}

void CALLBACK CounterClockwiseRotateByY() {

nAngleY++;

}

void myinit (void)

{

/* 将背景清为白色*/

glClearColor (0.0, 0.0,0.0, 1.0);

glShadeModel (GL_SMOOTH);

GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };

GLfloat specular[] = { 1.0, 1.0, 0.0, 1.0 };

GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };

GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat mat_shininess[] = { 128.0 };

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

glLightfv(GL_LIGHT1, GL_POSITION, light_position);

glLightfv (GL_LIGHT1, GL_AMBIENT, ambient);

glLightfv (GL_LIGHT1, GL_SPECULAR, specular);

glLightfv (GL_LIGHT1, GL_DIFFUSE, diffuse);

// 指定全局环境光

glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

// 指定视点:GL_TRUE:视点位于(,,),GL_FALSE:视点在无穷远glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT1);

glDepthFunc(GL_LEQUAL);

glEnable(GL_DEPTH_TEST);

glEnable(GL_AUTO_NORMAL);

glEnable(GL_NORMALIZE);

}

void CALLBACK reshape(GLsizei w, GLsizei h)

{

if (!h) return;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if (w <= h)

glOrtho (-500.0, 500.0, -500.0*(GLfloat)h/(GLfloat)w,

500.0*(GLfloat)h/(GLfloat)w, -500, 500);

else

glOrtho (-500.0*(GLfloat)w/(GLfloat)h,

500.0*(GLfloat)w/(GLfloat)h, -500.0, 500.0, -500, 500);

glMatrixMode(GL_MODELVIEW);

}

void CALLBACK display(void)

{

GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };

GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };

GLfloat mat_ambient_color[] = { 0.0, 0.8, 0.0, 1.0 };

GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };

GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };

GLfloat no_shininess[] = { 0.0 };

GLfloat low_shininess[] = { 5.0 };

GLfloat high_shininess[] = { 100.0 };

GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};

glLoadIdentity();

glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除背景

glRotated(nAngleX,1,0,0);

glRotated(nAngleY,0,1,0);

glRotated(nAngleZ,0,0,1);

glLineStipple(1, 0x3F07); // 指定点划格式

glEnable(GL_LINE_STIPPLE); // 进入点划模式

glBegin(GL_LINES);

// X轴:红

glColor3f (1.0, 0, 0);

glVertex3d(-490,0,0);

glVertex3d(490,0,0);

// Y轴:绿

glColor3f (0.0, 1.0, 0);

glVertex3d(0,-490,0);

glVertex3d(0,490,0);

// Z轴:蓝

glColor3f (0.0, 0.0, 1);

glVertex3d(0,0,-490);

glVertex3d(0,0,490);

glEnd();

glDisable(GL_LINE_STIPPLE);//离开点划模式

/* (1,1) draw sphere in first row, first column

* diffuse reflection only; no ambient or specular

*/

glPushMatrix();

glTranslatef (-375, 300, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (1,2) draw sphere in first row, second column

* diffuse and specular reflection; low shininess; no ambient

*/

glPushMatrix();

glTranslatef (-125, 300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (1,3) draw sphere in first row, third column

* diffuse and specular reflection; high shininess; no ambient

*/

glPushMatrix();

glTranslatef (125, 300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (1,4) draw sphere in first row, fourth column

* diffuse reflection; emission; no ambient or specular reflection */

glPushMatrix();

glTranslatef (375, 300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);

auxSolidSphere(100.0);

glPopMatrix();

/* (2,1) draw sphere in second row, first column

* ambient and diffuse reflection; no specular

*/

glPushMatrix();

glTranslatef (-375, 0.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (2,2) draw sphere in second row, second column

* ambient, diffuse and specular reflection; low shininess

*/

glPushMatrix();

glTranslatef (-125, 0.0, 0.0);

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

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (2,3) draw sphere in second row, third column

* ambient, diffuse and specular reflection; high shininess */

glPushMatrix();

glTranslatef (125, 0.0, 0.0);

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

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (2,4) draw sphere in second row, fourth column

* ambient and diffuse reflection; emission; no specular

*/

glPushMatrix();

glTranslatef (375, 0.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);

auxSolidSphere(100.0);

glPopMatrix();

/* (3,1) draw sphere in third row, first column

* colored ambient and diffuse reflection; no specular

*/

glPushMatrix();

glTranslatef (-375, -300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (3,2) draw sphere in third row, second column

* colored ambient, diffuse and specular reflection; low shininess */

glPushMatrix();

glTranslatef (-125, -300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (3,3) draw sphere in third row, third column

* colored ambient, diffuse and specular reflection; high shininess */

glPushMatrix();

glTranslatef (125, -300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);

auxSolidSphere(100.0);

glPopMatrix();

/* (3,4) draw sphere in third row, fourth column

* colored ambient and diffuse reflection; emission; no specular */

glPushMatrix();

glTranslatef (375, -300.0, 0.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);

glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);

glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);

glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);

auxSolidSphere(100.0);

glPopMatrix();

auxSwapBuffers();

}

int _tmain(int argc, _TCHAR* argv[])

{

auxInitDisplayMode (AUX_DOUBLE | AUX_RGBA|AUX_DEPTH);

auxInitPosition (0, 0, 1000, 700);

auxInitWindow ("材质示例");

myinit ();

auxKeyFunc (AUX_LEFT, ClockwiseRotateByY);

auxKeyFunc (AUX_RIGHT, CounterClockwiseRotateByY);

auxKeyFunc (AUX_UP, ClockwiseRotateByX);

auxKeyFunc (AUX_DOWN, CounterClockwiseRotateByX);

auxKeyFunc (AUX_D, ClockwiseRotateByZ);

auxKeyFunc (AUX_d, ClockwiseRotateByZ);

auxKeyFunc (AUX_U, CounterClockwiseRotateByZ);

auxKeyFunc (AUX_u, CounterClockwiseRotateByZ);

auxReshapeFunc(reshape);//回调函数

auxMainLoop(display);

return 0;

}

5.10.3 颜色材质模式

glMaterial*函数改变材质时开销较大,因此建议最好尽可能少的改变材质,以减少改变材质时所带来的性能开销,可采用另一种方式即改变材质颜色,相应函数为glColorMaterial(),说明如下:

void glColorMaterial(GLenum face,GLenum mode);

函数参数face指定面,值有GL_FRONT、GL_BACK或GL_FRONT_AND_BACK(缺省值)。mode指定材质成分,值有GL_AMBIENT、GL_DIFFUSE、GL_AMBIENT_AND_DIFFUSE(缺省值)、GL_SPECULAR或GLEMISSION。

注意:这个函数说明了两个独立的值,第一个参数说明哪一个面和哪些面被修改,而第二个参数说明这些面的哪一个或哪些材质成分要被修改。OpenGL并不为每一种face保持独立的mode变量。在调用glColorMterial()以后,首先需要用GL_COLOR_MATERIAL作为参数调用glEnable()来启动颜色材质,然后在绘图时调用glColor*()来改变当前颜色,或用glMaterial()来改变材质成分。当不用这种方式来改变材质时,可调用glDisable(GL_COLOR_MA TERIAL)来关闭取消。如下面一段代码:

glColorMaterial(GL_FRONT,GL_DIFFUSE);

glEnable(GL_COLOR_MATERIAL);

glColor3f(0.3,0.5,0.7);

/* draw some objects here. */

glcolor3f(0.0,1.0,0.0);

/* draw other objects here.*/

glDisable(GL_COLOR_MATERIAL);

当需要改变场景中大部分物体的单个材质时,最好调用glColorMaterial();当需要修改不止一个材质参数时,最好调用glMaterial*()。注意,当不需要颜色材质时一定要关闭它,以避免相应的开销。

注:该函数指定的不是光的强度,而是物体对光的反射率。如上例中指定了颜色材质的散射光属性,则下面的glColor3f(0.3,0.5,0.7)是说明了对散射光的R、G、B的反射率!此时还需要光源的散射光强度,二者缺一不可!

【综合示例EP5-8】使用glColorMterial()函数改变材质的散射光属性。按下鼠标的左键修改散射光颜色的红色分量,按下鼠标的中间键修改散射光颜色的绿色分量,按下鼠标的右键修改散射光颜色的蓝色分量,

完整的程序代码如下,粗体部分为新加入的代码。

#include"stdafx.h"

int nAngleY=0; // 沿Y轴旋转的角度

int nAngleX=0; // 沿X轴旋转的角度

int nAngleZ=0; // 沿Z轴旋转的角度

GLfloat diffuseMaterial[] = { 0.5, 0.5, 0.5, 1.0 };

void CALLBACK leftbutton (AUX_EVENTREC *event) {

diffuseMaterial[0] += 0.1;

if (diffuseMaterial[0] > 1.0)

diffuseMaterial[0] = 0.0;

}

void CALLBACK rightbutton (AUX_EVENTREC *event) {

diffuseMaterial[2] += 0.1;

if (diffuseMaterial[2] > 1.0)

diffuseMaterial[2] = 0.0;

}

void CALLBACK middlebutton (AUX_EVENTREC *event) {

diffuseMaterial[1] += 0.1;

if (diffuseMaterial[1] > 1.0)

diffuseMaterial[1] = 0.0;

}

void CALLBACK ClockwiseRotateByX()

{

nAngleX--;

}

void CALLBACK CounterClockwiseRotateByX()

{

nAngleX++;

}

void CALLBACK ClockwiseRotateByZ()

{

nAngleZ--;

}

OpenGL入门学习之七——使用光照来表现立体感

OpenGL入门学习之七——使用光照来表现立体感 2009-01-07 11:49 从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。因此对于人类而言,光线很大程度上表现了物体的立体感。 请看图1,图中绘制了两个大小相同的白色球体。其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。 图1 OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。但是在这之前,我们有必要了解一些基础知识。 一、建立光照模型 在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。 就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。 OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。光源就是光的来源,可以是前面所说的太阳或者电灯等。材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。

实验7 OpenGL光照

实验7 OpenGL光照 一、实验目的 了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效果。 二、实验内容 (1)下载并运行Nate Robin教学程序包中的lightmaterial 程序,试验不同的光照与材质系数; (2)运行示范代码1,了解光照与材质函数使用。 三、实验原理 为在场景中增加光照,需要执行以下步骤: (1)设置一个或多个光源,设定它的有关属性; (2)选择一种光照模型; (3)设置物体的材料属性。 具体见教材第8章8.6节用OpenGL生成真实感图形的相关内容。 四、实验代码 #include #include 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_LIGHT1 GLfloat 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_Ambient1); //开启灯光

第三章光照模型纹理映射

第三章光照模型及纹理映射 基本光照模型 1.在现实生活中,当光照在非透明物体上时,部分光线被物体吸收,剩余的部分光线被反射。人眼依靠这种反射光来感知物体的形状、颜色和其他细节。从光源投向物体的光称为入射光,从物体表面反射回的光称为反射光。 1.1光照模型概述 当光照射到物体表面上时,将出现3种情况: ●光从物体表面反射,形成反射光 ●光穿透物体,形成透射光 ●光被物体吸收,转化成为物体的内能 在上述三种情形的光线中,通常只有前2种情形的光线会对人眼产生视觉效果,使人察觉到物体的色彩变化。 OpenGL用一种近似的光照模型模拟现实世界的光照效果。在该模型中,仅当物体表面吸收和反射光线时,光源才会起做作用。每一个物体表面都假定是由某种特性的材料构成的。一种材料可能发出自己的光线,也可能在各个方向上发散一些射入的光线,还有可能像镜子一样在某个方向强烈地反射入射光。 1.2光照分量 在OpenGL的简化光照模型中,将光照分为4个独立的组成部分:辐射光、环境光、漫反射光和镜面反射光。 1)辐射光

辐射光是直接从物体或光源发出的,不受任何其他光源的影响。 2)环境光 环境光是这样一种光线,它被环境多次反射,以致于连初始 方向也难以确定。这种光线看起来就像来自于所有的方向, 当它照在一个物体表面时,它在所有的方向上等量地反射。 3)漫反射光 在被照射物体表面的反射光中,那些均匀地向各个方向反射 出去的光,称为漫反射光,如黑板反射就属于漫反射光 4)镜面反射光 镜面反射光是指超一定方向的反射光,如点光源照射光滑金 属球表面时,会在球表面形成一个特别亮的区域,呈现所谓 的高亮(Highlight>,这就是光源在该物体表面形成的镜面反射光(Specular Light>。点光源照射表面光滑的物体时,高亮区域小而亮;而点光源照射表面粗糙的物体时,高亮区域大而不亮。 1.3创建光源 光源有许多特性,如颜色、位置、方向等。不同特性的光源,作用在物体上的效果是不一样的。 1.3.1定义一个简单光源 在OpenGL中,定义一个光源是由函数glLight(>来实现的,该函数的原型为:void glLight(GLenum light,GLenum pname>; light为一个光源,pname为光源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值来定义的,分别描述光线中红绿蓝各成分的相对亮度。计算混合光的亮度时,则把相应的颜色亮度叠加即可,例如:环境光为(R1,G1,B1),散射光为(R2,G2,B2),镜面光为(R3,G3,B3),则混合后的光线为(R1+R2+R3,G1+G2+G3,B1+B2+B3)。 (3)材质: 材质是物体本身的一种属性,主要用来表征物体对不同颜色、不同类型光线的反射、吸收性能。 在OpenGL中设置材质参数,就是要指定这种材质对环境光、散射光、镜面光的反射能力,有时还需要说明该种材质是否具有发光能力。 在最终绘制每个像素时,OpenGL自行将物体材质的各分量与光线的各分量相乘再叠加,从而得到每个像素的RGB值。例如:光线为(R,G,B),材质为(MR,MG, MB),则最终绘制时颜色为(MR*R,MG*G,MB*B)。 (4)获得光照效果的一般过程为: a)使能光照:glEnable(GL_LIGHTING); b)设置一种光照模式:glLightModel*(); 如果只需要普通的无方向的环境光: GLfloat light_ambient[]={red,green,blue,alpha};//环境光的分值 //全局环境光的默认取值为(0.2,0.2,0.2,1.0) glLightModel*(GL_LIGHT_MODEL_AMBIENT,light_ambient); 如果需要在某个具体位置上放置某个光源,例如: GLfloat light_ambient[]={0.3,0.3,0.3,1.0};//环境光 glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient); GLfloat light_diffuse[]={0.7,0.7,0.7,1.0};//散射光 glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse); GLfloat light_specular[]={1.0,1.0,1.0,1.0};//镜面光 glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);

OpenGL光照与材质

OpenGL---------光照的基本知识 从生理学的角度上讲,眼睛之所以看见各种物体,是因为光线直接或间接的从它们那里到达了眼睛。人类对于光线强弱的变化的反应,比对于颜色变化的反应来得灵敏。因此对于人类而言,光线很大程度上表现了物体的立体感。 请看图1,图中绘制了两个大小相同的白色球体。其中右边的一个是没有使用任何光照效果的,它看起来就像是一个二维的圆盘,没有立体的感觉。左边的一个是使用了简单的光照效果的,我们通过光照的层次,很容易的认为它是一个三维的物体。 OpenGL对于光照效果提供了直接的支持,只需要调用某些函数,便可以实现简单的光照效果。但是在这之前,我们有必要了解一些基础知识。 一、建立光照模型 在现实生活中,某些物体本身就会发光,例如太阳、电灯等,而其它物体虽然不会发光,但可以反射来自其它物体的光。这些光通过各种方式传播,最后进入我们的眼睛——于是一幅画面就在我们的眼中形成了。 就目前的计算机而言,要准确模拟各种光线的传播,这是无法做到的事情。比如一个四面都是粗糙墙壁的房间,一盏电灯所发出的光线在很短的时间内就会经过非常多次的反射,最终几乎布满了房间的每一个角落,这一过程即使使用目前运算速度最快的计算机,也无法精确模拟。不过,我们并不需要精确的模拟各种光线,只需要找到一种近似的计算方式,使它的最终结果让我们的眼睛认为它是真实的,这就可以了。 OpenGL在处理光照时采用这样一种近似:把光照系统分为三部分,分别是光源、材质和光照环境。光源就是光的来源,可以是前面所说的太阳或者电灯等。材质是指接受光照的各种物体的表面,由于物体如何反射光线只由物体表面决定(OpenGL中没有考虑光的折射),材质特点就决定了物体反射光线的特点。光照环境是指一些额外的参数,它们将影响最终的光照画面,比如一些光线经过多次反射后,已经无法分清它究竟是由哪个光源发出,这时,指定一个“环境亮度”参数,可以使最后形成的画面更接近于真实情况。 在物理学中,光线如果射入理想的光滑平面,则反射后的光线是很规则的(这样的反射称为镜面反射)。光线如果射入粗糙的、不光滑的平面,则反射后的光线是杂乱的(这样的反射称为漫反射)。现实生活中的物体在反射光线时,并不是绝对的镜面反射或漫反射,但可以看成是这两种反射的叠加。对于光源发出的光线,可以分别设置其经过镜面反射和漫反射后的光线强度。对于被光线照射的材质,也可以分别设置光线经过镜面反射和漫反射后的光线强度。这些因素综合起来,就形成了最终的光照效果。 二、法线向量 在OpenGL中,法线的方向是用一个向量来表示。不幸的是,OpenGL并不会根据你所指定的多边形各个顶点来计算出这些多边形所构成的物体的表面的每个点的法线(这话听着有些迷糊),通常,为了实现光照效果,需要在代码中为每一个顶点指定其法线向量。 指定法线向量的方式与指定颜色的方式有雷同之处。在指定颜色时,只需要指定每一个顶点的颜色,OpenGL就可以自行计算顶点之间的其它点的颜色。并且,颜色一旦被指定,除非再指定新的颜色,否则以后指定的所有顶点都将以这一向量作为自己的颜色。在指定法线向量时,只需要指定每一个顶点的法线向量,OpenGL会自行计算顶点之间的其它点的法线向量。并且,法线向量一旦被指定,除非再指定新的法线向量,否则以后指定的所有顶点都将以这一向量作为自

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光照

计算机图形学实验指导(三) – OpenGL光照 1.光照简介 采用光照要做的工作包括:创建光源,激活光照以及光源,以及定义物体的材质。创建光源是要定义光源的特征,物体的材质则与光源一起决定到达人眼的光的颜色。若光源颜色为(LR,LG,LB),材质颜色为(MR,MG,MB),则到达人眼的颜色为(LR*MR, LG*MG, LB*MB)。 2.简单光照模型 一般来说,反射光可以分成三个分量,即环境反射、漫反射和镜面反射。环境反射分量假定入射光均匀地从周围环境入射至景物表面并等量地向各个方向反射出去,通常物体表面还会受到从周围环境来的反射光(如来自地面、天空、墙壁等的反射光)的照射,这些光常统称为环境光(Ambient Light);漫反射分量表示特定光源在景物表面的反射光中那些向空间各方向均匀反射出去的光,这些光常称为漫射光(Diffuse Light);镜面反射光为朝一定方向的反射光,如一个点光源照射一个金属球时会在球面上形成一块特别亮的区域,呈现所谓“高光(Highlight)”,它是光源在金属球面上产生的镜面反射光(Specular Light)。对于较光滑物体,其镜面反射光的高光区域小而亮;相反,粗糙表面的镜面反射光呈发散状态,其高光区域大而不亮。 3.OpenGL光源 光源有许多特性,如颜色、位置、方向等。选择不同的特性值,则对应的光源作用在物体上的效果也不一样,下面的函数定义了OpenGL的光源。 void glLightfv(GLenum light , GLenum pname, TYPE param) 其中第一个参数light指定所创建的光源号,如GL_LIGHT0、GL_LIGHT1、...、GL_LIGHT7。第二个参数pname指定光源特性,这个参数的具体信息见下表所示。最后一个参数设置相应的光源特性值。 pname 参数名说明 GL_AMBIENT RGBA模式下环境光 GL_DIFFUSE RGBA模式下漫反射光 GL_SPECULAR RGBA模式下镜面光 GL_POSITION 光源位置齐次坐标(x,y,z,w) GL_SPOT_DIRECTION 点光源聚光方向矢量(x,y,z) GL_SPOT_EXPONENT 点光源聚光指数 GL_SPOT_CUTOFF 点光源聚光截止角 例如:下面定义了一个位置在(1,1,1),没有环境光,镜面反射光和漫反射光都为白光的光源GLfloat light_position[] = { 1.0, 1.0, 1.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 );

Opengl实验报告及源代码实验六 颜色与光照

南昌大学实验报告 学生姓名:学号:专业班级: 实验类型:□验证□综合□设计□创新实验日期:2018.11 实验成绩: 一、实验名称 实验六颜色与光照 二、实验内容 1.指定几何模型的绘制颜色,使用平滑着色模式用多种不同的颜色绘制多边形; 2.通过定义光源、材质和光照模型属性渲染物体的光照效果; 3.创建一个3D虚拟场景,利用定向光、点光源和聚光灯等不同光源实现3D场景的光 照效果。 三、实验目的 1.了解RGBA颜色的实现原理,掌握利用Flat和Smooth着色模式来绘制不同颜色的物 体的方法; 2.掌握OpenGL光照模型,理解光源、材质和光照模型如何综合影响物体的光照效果。 3.掌握定向光、点光源和聚光灯的不同属性及三种光源光照效果的计算方法。 四、实验步骤 1.建立立方体几何模型。定义立方体顶点的位置坐标和纹理坐标,设置不同立方体在 世界坐标系中的位置: // Set up vertex data (and buffer(s)) and attribute pointers GLfloat vertices[] = { // Positions // Normals // Texture Coords -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,

基于OpenGL的三维图形的绘制_吴爱兰

PSLIBLINGS|WS_CLIPCHILDREN;(2)OnCreate 为了使OpenGL能在绘图表面(窗口或位图)上绘制图象,必须先对绘图表面进行初始化,既通过对象素格式的描述(分配并填充PIXELFORMATDESCRIPTOR结构)、选择(通过ChoosePixelFormat函数)和设置(通过SetPixelFormat函数),规定绘图表面的某些属性。此外,只有在OpenGL环境中,OpenGL命令才能被接受并执行,所以我们必须创建OpenGL绘制环境(由函数wgCreatContext完成)。在必要的情况下,还将进一步创建调色板。我们选择视图类消息句柄OnCreate作为完成这些工作的恰当场所。 (3)OnSize 窗口大小变动时会触发消息句柄,OnSize在此函数中,我们的目的是建立3D OpenGL坐标与2D屏幕坐标之间的映射,体现为做三件事: 获取当前的绘制环境。这个使用wgMakeCurrent函数来完成,函数如下所示,BOOL bResult=wgMakeCurrent(dc.m_Hdc,m_hrc); 设置映射方式。OpenGL大量使用矩阵运算,因为场地景到屏幕的变换,以及3D图形的3D旋转、平移和缩放都是采用矩阵变换实现的。在OnSize函数中,我们使用投影栈来设置我们观察物体的方法,总共用到四个函数,如下所示, GLdouble gldAspect=(GLdouble)cx/(GLdouble)cy; GlMatrixMode(GL_PROJECTION);//指定所使用的矩阵栈 GlLoadIdentity(); //清空矩阵栈GlPerspective(45.0,gldAspect,1.0,10.0);//设定用户的可见区域 GlViewport(0,0,cx,xy); //设置在用户区上的绘制区域 激活当前绘制环境。在使用多个绘 基于OpenGL的三维图形的绘制 吴爱兰1 楼建列2 1、浙江公路机械技工学校 310014 2、浙江经济职业技术学院教育技术中心 310018 一、OpenGL的简介 目前OpenGL是工业界公认的先进而强大的三维图形编程接口(3D API)。它有着功能完备的二维和三维图形处理能力,是理想的三维应用程序开发工具。它包含将近120个绘制点、线和多边形等3D图形原语的绘制命令,及其他众多的功能函数,能处理各种图形基本元素及图形特征效果,如明暗度、纹理贴图、Z缓冲、反走样、光照模型等。 OpenGL是Visual C++中附带的SDK(Software Development Kit)。它直接使用绘制环境,间接使用设备环境,因此设备环境中的当前画笔、画刷、颜色、字体等均对OpenGL绘制无任何影响。甚至GDI映射模式都对OpenGL不起作用。所以,使用MFC开发应用程序并采用OpenGL进行绘制,必须遵循一定的规范,先建立OpenGL绘制环境,然后才能使用OpenGL命令。 二、OpenGL绘图环境的设置 2.1 准备工作 为了能够使用OpenGL命令,必须要在预编译头文件中加入两个库函数,openggl32.lib、glu32.lib,如果还需要使用辅助库中所定义的函数,则需要再加入 glaux.lib 库函数。 2.2 消息句柄 (1)PrecreateWindow 为了使用OpenGL绘制,必须先在有关窗口的客户区中进行OpenGL初始化,即需要重载消息句柄PrecreateWindow并将窗口风格规定为:cs_style|=WS_SLI 制环境的情况下,即将离开时,应调用wglMakeCurrent来激活当前绘制环境,wglMakeCurrent(NULL,NULL); (4)OnDraw 此函数真正负责绘制3D图象,包括以下步骤: 在DC中选择并实现调色板; 调用wglMakeCurrent使绘制环境成为当前的; 调用OpenGL命令绘制场景; 如果使用双缓存像素格式,交替绘制缓存; 重新为DC选择原始的调色板。经过上述一系列步骤以后,OpenGL的绘图环境就已经设置完成,下面就可以通过OpenGL的绘图命令进行图形的绘制。 三、三维图形的绘制 设置完成OpenGL的绘图环境后,就可以在VC++中使用OpenGL三维函数库进行图形的绘制。函数的使用如下: glPolygonMode函数是用来选择多边形光栅化模式的。它的原型是voidglPolygonMode(Glenum face ,Glenummode),其中,参数face用来指定mode应用的多边形,对于正面多边形,必须为GL_FRONT,对于反面多边形,必须为GL_BACK,对于正面和反面多边形,必须为GL_FRONT_AND_BACK。参数mode用来指定多边形光栅化的方式,可以选择的值为GL_POINT、GL_LINE和GL_FILL。 glBegin和glEnd函数用来限定一组或多组图原的顶点定义。OpenGL绘制的所有复杂的三维物体都是由一定数量的基本图形元素(点、线、多边形)构成。曲线和曲面分别是由一系列直线段和多边形近似得到。基本图元类型由glBegin的参数设定,它的参数只有一个变量,该

图形学第十一课--OpenGL特殊光处理

第十四章 OpenGL特殊光处理 目录 14.1 光照模型 14.2 光源位置与衰减 14.3 聚光和多光源 14.4 光源位置与方向的控制 14.5 辐射光 本章内容是基础篇第七章的补充和提高。这一章主要讲述一些特殊光效果处理,如全局环境光、双面光照、光的衰减、聚光、多光源、光源位置的改变等等。读者若有兴趣,可以按照本章例程的方法作出许多变换,则会出现意想不到的效果,充分发挥你的艺术才能。 14.1、光照模型 OpenGL光照模型的概念由一下三部分组成:1)全局泛光强度、2)视点位置在景物附近还是在无穷远处、3)物体的正面和背面是否分别进行光照计算。 14.1.1 全局环境光 正如前面基础篇中所提到的一样,每个光源都能对一个场景提供环境光。此外,还有一个环境光,它不来自任何特定的光源,即称为全局环境光。下面用参数GL_LIGHT_MODEL_AMBIENT来说明全局环境光的RGBA强度: GLfloat lmodel_ambient[]={0.2,0.2,0.2,1.0}; glLightModelfv(GLLIGHT_MODEL_AMBIENT,lmodel_ambient); 在这个例子中,lmodel_ambient所用的值为GL_LIGHT_MODEL_AMBIENT的缺省值。这些数值产生小量的白色环境光。 14.1.2 近视点与无穷远视点 视点位置能影响镜面高光的计算,也就是说,顶点的高光强度依赖于顶点法向量,从顶点到光源的方向和从顶点到视点的方向。实际上,调用光照函数并不能移动视点。但是可以对光照计算作出不同的假定,这样视点似乎移动了。对于一个无穷远视点,视点到任何顶点的方向保持固定,缺省时为无穷远视点。对于一个近视点,物体每个顶点到视点的方向是不同的,需要逐个计算,从而整体性能降低,但效果更真实。下面一句函数代码是假定为近视点: glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE); 这个调用把视点放在视点坐标系的原点处。若要切换到无穷远视点,只需将

相关主题
相关文档
最新文档