#include <gl/glut.h>
#include <stdio.h>
#include <stdlib.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 material_shininess[]={0.6*128};
GLuint fogMode[]={GL_EXP,GL_EXP2,GL_LINEAR};//雾气的模式
GLuint fogfilter=2;//使用哪一种雾气
/* GL_EXP - 充满整个屏幕的基本渲染的雾。它能在较老的PC上工作,因此并不是特别像雾。
GL_EXP2 - 比GL_EXP更进一步。它也是充满整个屏幕,但它使屏幕看起来更有深度。
GL_LINEAR - 最好的渲染模式。物体淡入淡出的效果更自然。*/
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 Initial(void)
{
glClearColor(0.5,0.5,0.5,1.0);
//GL_LIGHT0是光源的标识号,标识号由GL_LIGHTi组成(i从0到GL_MAX_LIGHTS)
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);//GL_AMBIENT:光源的周围颜色强度
glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);//GL_DIFFUSE:光源的散射强度
glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);//GL_SPECULAR:光源的镜面反射强度
glLightfv(GL_LIGHT0,GL_POSITION,light_position);//GL_POSITION:光源的位置
glEnable(GL_LIGHTING);//启动光照模型
glEnable(GL_LIGHT0);//使光源GL_LIGHT0有效,OpenGL中一共可以定义GL_LIGHT0~GL_LIGHT7八个光源
//OpenGL中的材质是指构成三维实体的材料在光照模型中对于红、绿、蓝三原色的反射率
glMaterialfv(GL_FRONT,GL_AMBIENT,material_ambient);//定义环境光反射率
glMaterialfv(GL_FRONT,GL_DIFFUSE,material_diffuse);//定义漫射光反射率
glMaterialfv(GL_FRONT,GL_SPECULAR,material_specular);//定义镜面光反射率
glMaterialfv(GL_FRONT,GL_SHININESS,material_shininess);//定义高光指数
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);//如果激活,做深度比较,并且更新深度缓冲
glDepthFunc(GL_LESS);//设置深度测试函数,有 GL_LESS 和 GL_LEQUAL
glEnable(GL_AUTO_NORMAL);//如果激活,做曲面法线矢量分析当 GL_MAP2_VERTEX_3或者GL_MAP2_VERTEX_4产生了 顶点坐标
glEnable(GL_NORMALIZE);//如果激活,法线矢量由 glNormal指定,并且在转换后按单位长度进行缩放
glFrontFace(GL_CW);//设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
//glFrontFace(GL_CW);设置CW方向为“正面”,CW即ClockWise,顺时针
glFogi(GL_FOG_MODE,fogMode[fogfilter]);//建立雾的过滤模式
glFogfv(GL_FOG_COLOR,fogColorWhite);//设置雾的颜色
glFogf(GL_FOG_DENSITY,fogDensity);//设置雾的密度
glFogf(GL_FOG_START,0.0);//雾气的开始位置
glFogf(GL_FOG_END,15.0);//雾气的结束位置
glEnable(GL_FOG);
glHint(GL_FOG_HINT,GL_DONT_CARE);
/* glHint(GL_FOG_HINT, hintval)
gl_dont_care - 由OpenGL决定使用何种雾效(对每个顶点还是每个像素执行雾效计算)和一个未知的公式(?)
gl_nicest - 对每个像素执行雾效计算(效果好)
gl_fastest - 对每个顶点执行雾效计算 (更快,但效果不如上面的好)*/
}
static void myKeyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 33://shift+1,增加雾化浓度
printf("1/n");
fogDensity*=1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case 64://shift+2,减弱雾化浓度
printf("2/n");
fogDensity/=1.10;
glFogi(GL_FOG_MODE,GL_EXP);
glFogf(GL_FOG_DENSITY,fogDensity);
glutPostRedisplay();
break;
case 35://shift+3,设置雾化的起始点和终止点
printf("3/n");
glFogi(GL_FOG_START,0.0);
glFogi(GL_FOG_END,8.0);
glutPostRedisplay();
break;
case 36://shift+4,改变雾化方程
printf("4/n");
glFogi(GL_FOG_MODE,fogMode[1]);
glutPostRedisplay();
break;
case 37://shift+5,改变雾化方程
printf("5/n");
glFogi(GL_FOG_MODE,fogMode[2]);
glutPostRedisplay();
break;
case 94://shift+6,雾化颜色由白改为绿色
printf("6/n");
glFogfv(GL_FOG_COLOR,fogColorGreen);
glutPostRedisplay();
break;
case 27://Esc
exit(0);
default:
break;
}
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();//glPushMatrix();把当前矩阵保存在栈顶上;glPopMatrix();弹出栈顶上的矩阵,恢复原来的矩阵。
//用push和pop的目的是为了保护原来的矩阵在一系列变换操作后被破坏
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(GLsizei w,GLsizei h)
{
glViewport(0,0,w,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);
glutInitWindowSize(300,300);
glutInitWindowPosition(100,100);
glutCreateWindow("FOG");
Initial();
glutKeyboardFunc(myKeyboard);
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}