OpenGL编程轻松入门(三)
(由同事黄燕创作)
1. 使用光照和材质
使用了光照和材质可以使物体更逼真,具有立体感。例4就是没有使用光照使呈现在我们眼前的物体茶壶和立方体没有立体感。
例6:绘制三个使用不同材质的球体。
#include <windows.h>
#include <GL/glut.h>
GLfloat light_position[] = {0.0,3.0,6.0,0.0};
GLfloat no_mat[] = {0.0,0.0,0.0,1.0};
GLfloat mat_grey_ambient[] = {0.5,0.5,0.5,1.0};
GLfloat mat_red_ambient[] = {0.0,0.0,1.0,1.0};
GLfloat mat_diffuse[] = {0.8,0.2,0.5,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};
void myInit(void)
{
glLightfv(GL_LIGHT2,GL_POSITION,light_position);//设置光源
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);//指定深度比较中使用的数值
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
/*为光照模型指定材质参数*/
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);
glColorMaterial(GL_FRONT,GL_AMBIENT);//使材质色跟踪当前颜色
glEnable(GL_COLOR_MATERIAL);
/*第一个球形*/
glPushMatrix();
glColor3fv(no_mat);
glTranslatef(-2.5,1.5,0.0);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
/*第二个球形*/
glPushMatrix();
glColor3fv(mat_grey_ambient);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
/*第三个球形*/
glPushMatrix();
glColor3fv(mat_red_ambient);
glTranslatef(2.5,-1.5,0.0);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
glDisable(GL_COLOR_MATERIAL);
glPopMatrix();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w <= h)
glOrtho(-5.5,5.5,-5.5*(GLfloat)h/(GLfloat)w,5.5*(GLfloat)h/(GLfloat)w,-5.5,5.5);
else
glOrtho(-5.5*(GLfloat)w/(GLfloat)h,5.5*(GLfloat)w/(GLfloat)h,-5.5,5.5,-5.5,5.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(100,100);
/*创建窗口*/
glutCreateWindow(" Light&Material ");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
函数myInit中:
l glLight设置光源的参数。有三个参数,第一个参数指定光照的数目,最大为8。第二个参数为光照的单值光源参数。第三个参数为赋给第二个参数的值,本例中即为将light_position的值赋值给GL_POSITION。
display函数中
l glMaterial为光照模型指定材质参数。第一个参数为改变材质的面,其值必为GL_FRONT, GL_BACK或GL_FRONT_AND_BACK中的一个。第二个参数为需要改变的材质参数。第三个参数为赋给参数二的值或指向值的指针。本例中均为指针。
l glColorMateria使材质色跟踪当前颜色。第一个参数指定哪一个面需要使材质色跟踪当前颜色。第二个参数指定哪个参数需要跟踪颜色。
2. 纹理映射
例6:绘制三个使用不同材质的球体。
#include <windows.h>
#include <GL/glut.h>
GLfloat light_position[] = {0.0,3.0,6.0,0.0};
GLfloat no_mat[] = {0.0,0.0,0.0,1.0};
GLfloat mat_grey_ambient[] = {0.5,0.5,0.5,1.0};
GLfloat mat_red_ambient[] = {0.0,0.0,1.0,1.0};
GLfloat mat_diffuse[] = {0.8,0.2,0.5,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};
void myInit(void)
{
glLightfv(GL_LIGHT2,GL_POSITION,light_position);//设置光源
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);//指定深度比较中使用的数值
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
/*为光照模型指定材质参数*/
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);
glColorMaterial(GL_FRONT,GL_AMBIENT);//使材质色跟踪当前颜色
glEnable(GL_COLOR_MATERIAL);
/*第一个球形*/
glPushMatrix();
glColor3fv(no_mat);
glTranslatef(-2.5,1.5,0.0);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
/*第二个球形*/
glPushMatrix();
glColor3fv(mat_grey_ambient);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
/*第三个球形*/
glPushMatrix();
glColor3fv(mat_red_ambient);
glTranslatef(2.5,-1.5,0.0);
glRotatef(15.0,1.0,0.0,0.0);
glutSolidSphere(1.2,20.0,20.0);
glPopMatrix();
glDisable(GL_COLOR_MATERIAL);
glPopMatrix();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w <= h)
glOrtho(-5.5,5.5,-5.5*(GLfloat)h/(GLfloat)w,5.5*(GLfloat)h/(GLfloat)w,-5.5,5.5);
else
glOrtho(-5.5*(GLfloat)w/(GLfloat)h,5.5*(GLfloat)w/(GLfloat)h,-5.5,5.5,-5.5,5.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(100,100);
/*创建窗口*/
glutCreateWindow(" Light&Material ");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
函数myInit中:
l glLight设置光源的参数。有三个参数,第一个参数指定光照的数目,最大为8。第二个参数为光照的单值光源参数。第三个参数为赋给第二个参数的值,本例中即为将light_position的值赋值给GL_POSITION。
display函数中
l glMaterial为光照模型指定材质参数。第一个参数为改变材质的面,其值必为GL_FRONT, GL_BACK或GL_FRONT_AND_BACK中的一个。第二个参数为需要改变的材质参数。第三个参数为赋给参数二的值或指向值的指针。本例中均为指针。
l glColorMateria使材质色跟踪当前颜色。第一个参数指定哪一个面需要使材质色跟踪当前颜色。第二个参数指定哪个参数需要跟踪颜色。
2. 纹理映射
纹理我们可以简单的理解为物体表面的花纹。同样的物体我们可以加上不同的纹理。我们可以使用现成的纹理也可以自己做一个新的纹理。
例7:绘制一个简单的二维纹理图,并将该图像映射到一个四边形上。
#include <stdlib.h>
#include <GL/glut.h>
#define imageWidth 64
#define imageHeight 64
GLubyte image[imageWidth][imageHeight][3];
/*绘制一个简单的二维纹理图*/
void makeImage(void)
{
int i,j,r,g,b;
/*根据点的位置设置不同的颜色*/
for(i = 0;i < imageWidth;i++)
{
for(j = 0;j <imageHeight;j++)
{
r = (i*j)%255;
g = (i*i)%255;
b = (j*j)%255;
image[i][j][0] = (GLubyte)r;
image[i][j][1] = (GLubyte)g;
image[i][j][2] = (GLubyte)b;
}
}
}
void myInit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
makeImage();
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
/*指定二维纹理映射*/
glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);
/*设置纹理参数*/
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
/*设置纹理环境参数*/
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_FLAT);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
/*将纹理映射到四边形上*/
glBegin(GL_QUADS);
/*纹理的坐标和四边形顶点的对应*/
glTexCoord2f(0.0,0.0); glVertex3f(-1.0,1.0,0.0);
glTexCoord2f(0.0,1.0); glVertex3f(-1.0,-1.0,0.0);
glTexCoord2f(1.0,1.0); glVertex3f(1.0,-1.0,0.0);
glTexCoord2f(1.0,0.0); glVertex3f(1.0,1.0,0.0);
glEnd();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat)h,1.0,30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char **argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(300,300);
glutInitWindowPosition(200,200);
/*创建窗口*/
glutCreateWindow(" Texture ");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
l void glTexImag2D(GLenum target,GLint level,GLint component,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid *pixels);
target 指目标纹理,必须为GL_TEXTURE_2D类型。
Level 细节层次数。第0层为基本图像级别。
components指纹理的颜色组成数,必须为1,2,3或4。本例中为3。这个数字的改变会影响所绘纹理的颜色。
width和heigth分别为纹理图像的宽和高。MSDN上的帮组说这两个值必为2^n+2,但我发现这两个值必为2^n。
border 边界的宽度。
format 指定像素数据格式。可选择值为GL_COLOR_INDEX ,GL_RED ,GL_GREEN,GL_BLUE ,GL_ALPHA ,GL_RGB ,GL_RGBA ,GL_BGR_EXT ,GL_BGR_EXT ,GL_BGRA_EXT ,GL_BGRA_EXT, GL_LUMINANCE,GL_LUMINANCE_ALPHA
例7:绘制一个简单的二维纹理图,并将该图像映射到一个四边形上。
#include <stdlib.h>
#include <GL/glut.h>
#define imageWidth 64
#define imageHeight 64
GLubyte image[imageWidth][imageHeight][3];
/*绘制一个简单的二维纹理图*/
void makeImage(void)
{
int i,j,r,g,b;
/*根据点的位置设置不同的颜色*/
for(i = 0;i < imageWidth;i++)
{
for(j = 0;j <imageHeight;j++)
{
r = (i*j)%255;
g = (i*i)%255;
b = (j*j)%255;
image[i][j][0] = (GLubyte)r;
image[i][j][1] = (GLubyte)g;
image[i][j][2] = (GLubyte)b;
}
}
}
void myInit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
makeImage();
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
/*指定二维纹理映射*/
glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);
/*设置纹理参数*/
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
/*设置纹理环境参数*/
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_FLAT);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
/*将纹理映射到四边形上*/
glBegin(GL_QUADS);
/*纹理的坐标和四边形顶点的对应*/
glTexCoord2f(0.0,0.0); glVertex3f(-1.0,1.0,0.0);
glTexCoord2f(0.0,1.0); glVertex3f(-1.0,-1.0,0.0);
glTexCoord2f(1.0,1.0); glVertex3f(1.0,-1.0,0.0);
glTexCoord2f(1.0,0.0); glVertex3f(1.0,1.0,0.0);
glEnd();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat)h,1.0,30.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc,char **argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(300,300);
glutInitWindowPosition(200,200);
/*创建窗口*/
glutCreateWindow(" Texture ");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
l void glTexImag2D(GLenum target,GLint level,GLint component,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid *pixels);
target 指目标纹理,必须为GL_TEXTURE_2D类型。
Level 细节层次数。第0层为基本图像级别。
components指纹理的颜色组成数,必须为1,2,3或4。本例中为3。这个数字的改变会影响所绘纹理的颜色。
width和heigth分别为纹理图像的宽和高。MSDN上的帮组说这两个值必为2^n+2,但我发现这两个值必为2^n。
border 边界的宽度。
format 指定像素数据格式。可选择值为GL_COLOR_INDEX ,GL_RED ,GL_GREEN,GL_BLUE ,GL_ALPHA ,GL_RGB ,GL_RGBA ,GL_BGR_EXT ,GL_BGR_EXT ,GL_BGRA_EXT ,GL_BGRA_EXT, GL_LUMINANCE,GL_LUMINANCE_ALPHA
type 指定像素数据类型。可选择值为GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, and GL_FLOAT.
pixels 指向存储在内存中的图像数据的指针。
l glTexParameter 设置纹理参数。三个参数。第一个参数指定纹理目标,必为GL_TEXTURE_1D或GL_TEXTURE_2D;第二个参数为指定单值纹理参数的名称,第三个参数为赋给第二个参数的值。
l glTexEnv 设置纹理环境参数。三个参数。第一个参数为纹理环境,必为GL_TEXTURE_ENV。第二个参数为纹理环境参数的名称。第三个参数为单值符号常数或指向参数数组的指针。
l glTexCoord 设置当前纹理坐标。
3. 特殊效果操作
pixels 指向存储在内存中的图像数据的指针。
l glTexParameter 设置纹理参数。三个参数。第一个参数指定纹理目标,必为GL_TEXTURE_1D或GL_TEXTURE_2D;第二个参数为指定单值纹理参数的名称,第三个参数为赋给第二个参数的值。
l glTexEnv 设置纹理环境参数。三个参数。第一个参数为纹理环境,必为GL_TEXTURE_ENV。第二个参数为纹理环境参数的名称。第三个参数为单值符号常数或指向参数数组的指针。
l glTexCoord 设置当前纹理坐标。
3. 特殊效果操作
每个物体在不同的环境在会有不同的视觉效果。为了使效果更加真实需要增加特殊效果。
例8:绘制三个互相重叠的矩形,这三个矩形从左到右分别为绿、红、蓝。其中红色、蓝色矩形的透明度分别为50%的透明度,即alpha值为0.5。
#include <stdlib.h>
#include <GL/glut.h>
void myInit(void)
{
glClearColor(0.2,0.8,0.8,0.0);//将背景设置为湖蓝色
glEnable(GL_BLEND);//激活GL_BLEND
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//指定像素的数学算法
glEnable(GL_FLAT);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
/*绘制一个绿色的矩形 alpha = 1.0*/
glColor4f(0.0,1.0,0.0,1.0);
glBegin(GL_POLYGON);
glVertex3f(-0.75,0.5,0.0);
glVertex3f(-0.75,-0.75,0.0);
glVertex3f(0.5,-0.75,0.0);
glVertex3f(0.5,0.5,0.0);
glEnd();
/*绘制一个红色的矩形 alpha = 0.5*/
glColor4f(1.0,0.0,0.0,0.5);
glBegin(GL_POLYGON);
glVertex3f(-0.25,1.0,0.0);
glVertex3f(-0.25,-0.25,0.0);
glVertex3f(1.0,-0.25,0.0);
glVertex3f(1.0,1.0,0.0);
glEnd();
/*绘制一个蓝色的矩形 alpha = 0.5*/
glColor4f(0.0,0.0,1.0,0.5);
glBegin(GL_POLYGON);
glVertex3f(0.25,1.5,0.0);
glVertex3f(0.25,0.25,0.0);
glVertex3f(1.5,0.25,0.0);
glVertex3f(1.5,1.5,0.0);
glEnd();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<h)
glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5);
else
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,-1.5,1.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.4,0.0,0.0);
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(300,400);
glutInitWindowPosition(200,200);
/*创建窗口*/
glutCreateWindow("BLEND POLYGON");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return(0);
}
l glBlendFunc(GLenum sfactor,GLenum dfactor) 指定像素算法。sfactor指定红,绿,蓝及alpha源混合因素是如何计算的。dfactor指定红,绿,蓝及alpha目标混合因素是如何计算的。
例9:绘制一个被雾化的圆锥体,为了观察不同的雾化参数,程序中加入了键盘操作。“1”,“2”键分别增加和减弱雾化浓度,“3”设置雾化的起始点和终止点,“4”和“5”键改变雾化方程,“6”将雾化颜色由白改为绿色。
#include <stdlib.h>
#include <GL/glut.h>
GLfloat light_ambient[] = {0.1,0.1,0.1,0.0};
GLfloat light_diffuse[] = {1.0,1.0,1.0,0.0};
GLfloat light_specular[] = {1.0,1.0,1.0,0.0};
GLfloat light_position[] = {-10.0,0.0,5.0,0.0};
GLfloat material_ambient[] = {0.1745,0.01175,0.01175};
GLfloat material_diffuse[] = {0.61424,0.04136,0.04136};
GLfloat material_specular[] = {0.727811,0.626959,0.62659};
GLfloat fogColorWhite[] = {1.0,1.0,1.0,1.0};
GLfloat fogColorGreen[] = {0.0,1.0,0.0,1.0};
float fogDensity = 0.02;
void myInit(void)
{
/*设置背景色*/
glClearColor(0.5,0.5,0.5,1.0);
/*设置光照*/
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,material_ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular);
glMaterialf(GL_FRONT,GL_SHININESS,0.6*128);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glFrontFace(GL_CW);
/*设置雾化*/
glEnable(GL_FOG);
glFogi(GL_FOG_MODE,GL_LINEAR);
glFogfv(GL_FOG_COLOR,fogColorWhite);
glFogf(GL_FOG_DENSITY,fogDensity);
glFogf(GL_FOG_START,0.0);
glFogf(GL_FOG_END,15.0);
glHint(GL_FOG_HINT,GL_DONT_CARE);
}
/*根据不同的键值设置不同的雾化效果*/
static void myKey(unsigned char key,int x,int y)
{
switch(key)
{
case'1':
fogDensity *= 1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case'2':
fogDensity /= 1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case'3':
glFogi(GL_FOG_START,0.0);
glFogi(GL_FOG_END,8.0);
glutPostRedisplay();
break;
case'4':
glFogi(GL_FOG_MODE,GL_EXP2);
glutPostRedisplay();
break;
case'5':
glFogi(GL_FOG_MODE,GL_LINEAR);
glutPostRedisplay();
break;
case'6':
glFogfv(GL_FOG_COLOR,fogColorGreen);
glutPostRedisplay();
break;
case 27:
exit(0);
default:
break;
}
}
/*绘制圆锥体*/
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-4.0,4.0,0.0);
glRotatef(30.0,1.0,1.0,0.0);
glutSolidCone(1.0,50.0,20.0,20.0);
glPopMatrix();
glutSwapBuffers();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(100.0,1.0,1.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-15.5);
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(300,300);
glutInitWindowPosition(100,100);
/*创建窗口*/
glutCreateWindow(" FOG ");
/*绘制与显示*/
myInit();
glutKeyboardFunc(myKey);
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
l glFog指定雾化参数。后面不同的字母表明参数的数据类型。f表示float,i表示integer,v表示vector,也就是表明一个指针。
GL_FOG_MODE是一个单值整数或浮点数,该数值指定了用来计算雾化融合因子f的方程。
GL_DENSITY 是一个单值整数或浮点数,该值指定雾化浓度。
GL_FOG_START 是一个单值整数或浮点数,该值指定雾化的起始值。
GL_FOG_END是一个单值整数或浮点数,该值指定雾化的终止值。
GL_FOG_INDEX是一个单值整数或浮点数,该值指定雾化索引值if,缺省的雾化索引值为0.0。
GL_FOG_COLOR包含4个整数值或浮点数值,这些数值指定的是雾化颜色Cf,整数值进行线性映射。
l glHint指定实现的线索。本例中GL_FOG_HINT指定雾化计算精度。GL_DONT_CARE指对选项不做考虑。
本例中还涉及到键盘操作,glutKeyboardFun。此函数注册当前窗口的键盘回调函数。因为这不是本节的主要内容,我们只简单提一下。此函数的原形为void glutKeyboardFunc (void(*func)(unsigned char key,int x,int y))所以我们自己写的回调函数必须按照原形上规定的写。
例8:绘制三个互相重叠的矩形,这三个矩形从左到右分别为绿、红、蓝。其中红色、蓝色矩形的透明度分别为50%的透明度,即alpha值为0.5。
#include <stdlib.h>
#include <GL/glut.h>
void myInit(void)
{
glClearColor(0.2,0.8,0.8,0.0);//将背景设置为湖蓝色
glEnable(GL_BLEND);//激活GL_BLEND
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//指定像素的数学算法
glEnable(GL_FLAT);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
/*绘制一个绿色的矩形 alpha = 1.0*/
glColor4f(0.0,1.0,0.0,1.0);
glBegin(GL_POLYGON);
glVertex3f(-0.75,0.5,0.0);
glVertex3f(-0.75,-0.75,0.0);
glVertex3f(0.5,-0.75,0.0);
glVertex3f(0.5,0.5,0.0);
glEnd();
/*绘制一个红色的矩形 alpha = 0.5*/
glColor4f(1.0,0.0,0.0,0.5);
glBegin(GL_POLYGON);
glVertex3f(-0.25,1.0,0.0);
glVertex3f(-0.25,-0.25,0.0);
glVertex3f(1.0,-0.25,0.0);
glVertex3f(1.0,1.0,0.0);
glEnd();
/*绘制一个蓝色的矩形 alpha = 0.5*/
glColor4f(0.0,0.0,1.0,0.5);
glBegin(GL_POLYGON);
glVertex3f(0.25,1.5,0.0);
glVertex3f(0.25,0.25,0.0);
glVertex3f(1.5,0.25,0.0);
glVertex3f(1.5,1.5,0.0);
glEnd();
glFlush();
}
void myReshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<h)
glOrtho(-1.5,1.5,-1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w,-1.5,1.5);
else
glOrtho(-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h,-1.5,1.5,-1.5,1.5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.4,0.0,0.0);
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(300,400);
glutInitWindowPosition(200,200);
/*创建窗口*/
glutCreateWindow("BLEND POLYGON");
/*绘制与显示*/
myInit();
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return(0);
}
l glBlendFunc(GLenum sfactor,GLenum dfactor) 指定像素算法。sfactor指定红,绿,蓝及alpha源混合因素是如何计算的。dfactor指定红,绿,蓝及alpha目标混合因素是如何计算的。
例9:绘制一个被雾化的圆锥体,为了观察不同的雾化参数,程序中加入了键盘操作。“1”,“2”键分别增加和减弱雾化浓度,“3”设置雾化的起始点和终止点,“4”和“5”键改变雾化方程,“6”将雾化颜色由白改为绿色。
#include <stdlib.h>
#include <GL/glut.h>
GLfloat light_ambient[] = {0.1,0.1,0.1,0.0};
GLfloat light_diffuse[] = {1.0,1.0,1.0,0.0};
GLfloat light_specular[] = {1.0,1.0,1.0,0.0};
GLfloat light_position[] = {-10.0,0.0,5.0,0.0};
GLfloat material_ambient[] = {0.1745,0.01175,0.01175};
GLfloat material_diffuse[] = {0.61424,0.04136,0.04136};
GLfloat material_specular[] = {0.727811,0.626959,0.62659};
GLfloat fogColorWhite[] = {1.0,1.0,1.0,1.0};
GLfloat fogColorGreen[] = {0.0,1.0,0.0,1.0};
float fogDensity = 0.02;
void myInit(void)
{
/*设置背景色*/
glClearColor(0.5,0.5,0.5,1.0);
/*设置光照*/
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,material_ambient);
glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse);
glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular);
glMaterialf(GL_FRONT,GL_SHININESS,0.6*128);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glFrontFace(GL_CW);
/*设置雾化*/
glEnable(GL_FOG);
glFogi(GL_FOG_MODE,GL_LINEAR);
glFogfv(GL_FOG_COLOR,fogColorWhite);
glFogf(GL_FOG_DENSITY,fogDensity);
glFogf(GL_FOG_START,0.0);
glFogf(GL_FOG_END,15.0);
glHint(GL_FOG_HINT,GL_DONT_CARE);
}
/*根据不同的键值设置不同的雾化效果*/
static void myKey(unsigned char key,int x,int y)
{
switch(key)
{
case'1':
fogDensity *= 1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case'2':
fogDensity /= 1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case'3':
glFogi(GL_FOG_START,0.0);
glFogi(GL_FOG_END,8.0);
glutPostRedisplay();
break;
case'4':
glFogi(GL_FOG_MODE,GL_EXP2);
glutPostRedisplay();
break;
case'5':
glFogi(GL_FOG_MODE,GL_LINEAR);
glutPostRedisplay();
break;
case'6':
glFogfv(GL_FOG_COLOR,fogColorGreen);
glutPostRedisplay();
break;
case 27:
exit(0);
default:
break;
}
}
/*绘制圆锥体*/
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(-4.0,4.0,0.0);
glRotatef(30.0,1.0,1.0,0.0);
glutSolidCone(1.0,50.0,20.0,20.0);
glPopMatrix();
glutSwapBuffers();
}
void myReshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(100.0,1.0,1.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-15.5);
}
int main(int argc,char ** argv)
{
/*初始化*/
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(300,300);
glutInitWindowPosition(100,100);
/*创建窗口*/
glutCreateWindow(" FOG ");
/*绘制与显示*/
myInit();
glutKeyboardFunc(myKey);
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
l glFog指定雾化参数。后面不同的字母表明参数的数据类型。f表示float,i表示integer,v表示vector,也就是表明一个指针。
GL_FOG_MODE是一个单值整数或浮点数,该数值指定了用来计算雾化融合因子f的方程。
GL_DENSITY 是一个单值整数或浮点数,该值指定雾化浓度。
GL_FOG_START 是一个单值整数或浮点数,该值指定雾化的起始值。
GL_FOG_END是一个单值整数或浮点数,该值指定雾化的终止值。
GL_FOG_INDEX是一个单值整数或浮点数,该值指定雾化索引值if,缺省的雾化索引值为0.0。
GL_FOG_COLOR包含4个整数值或浮点数值,这些数值指定的是雾化颜色Cf,整数值进行线性映射。
l glHint指定实现的线索。本例中GL_FOG_HINT指定雾化计算精度。GL_DONT_CARE指对选项不做考虑。
本例中还涉及到键盘操作,glutKeyboardFun。此函数注册当前窗口的键盘回调函数。因为这不是本节的主要内容,我们只简单提一下。此函数的原形为void glutKeyboardFunc (void(*func)(unsigned char key,int x,int y))所以我们自己写的回调函数必须按照原形上规定的写。