- 理论基础
雾效果:计算机图像有时候由于过于清晰和锐利,反而显得不太逼真。我们可以通过添加雾效果,使整幅图像变得更加逼真。所谓雾效果,就是使远处的物体看上去逐渐变得模糊。雾效果可以提高性能,因为它可以不绘制那些因为雾的影响而不可见的物体。其实现原理其实就是根据雾距离观察点的距离计算出一个混合因子,然后用它把雾颜色与目标颜色进行混合得到的效果。
- 实例代码
1,RGBA模式下的5个雾化球体
#include "GLTools.h"
#include "GLShaderManager.h"
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
static GLint fogMode;
static void init(void)
{
GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 };
glEnable(GL_DEPTH_TEST);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
{ //{}使模块划分更加清楚
GLfloat mat[3] = {0.1745, 0.01175, 0.01175};
glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
mat[0] = 0.61424; mat[1] = 0.04136; mat[2] = 0.04136;
glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
mat[0] = 0.727811; mat[1] = 0.626959; mat[2] = 0.626959;
glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
glMaterialf (GL_FRONT, GL_SHININESS, 0.6*128.0);
}
glEnable(GL_FOG);//激活雾效果
{
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0};
/*雾方程式模式,有三种形式,根据物体距离观察点的距离能
够算得一个雾因子(默认是计算机自动算出的,但我们也可以自
己控制雾因子),雾就是通过雾因子把雾颜色与源片段的颜色进
行混合得到的*/
fogMode = GL_EXP;
glFogi (GL_FOG_MODE, fogMode);
glFogfv (GL_FOG_COLOR, fogColor);//雾颜色
glFogf (GL_FOG_DENSITY, 0.35);//雾密度
glHint (GL_FOG_HINT, GL_DONT_CARE);//在渲染质量与速度上没有偏向
glFogf (GL_FOG_START, 1.0);//雾开始值(距离观察点开始距离)
glFogf (GL_FOG_END, 5.0);//雾结束值
}
glClearColor(0.5, 0.5, 0.5, 1.0);
}
static void renderSphere (GLfloat x, GLfloat y, GLfloat z)
{
glPushMatrix();
glTranslatef (x, y, z);
glutSolidSphere(0.4, 16, 16);
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderSphere (-2., -0.5, -1.0);
renderSphere (-1., -0.5, -2.0);
renderSphere (0., -0.5, -3.0);
renderSphere (1., -0.5, -4.0);
renderSphere (2., -0.5, -5.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho (-2.5, 2.5, -2.5*(GLfloat)h/(GLfloat)w,
2.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho (-2.5*(GLfloat)w/(GLfloat)h,
2.5*(GLfloat)w/(GLfloat)h, -2.5, 2.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
}
void keyboard(unsigned char key, int x, int y)
{
//雾效果逼真程度:GL_EXP < GL_EXP2 < GL_LINEAR
switch (key) {
case 'f':
case 'F':
if (fogMode == GL_EXP) {
fogMode = GL_EXP2;
printf ("Fog mode is GL_EXP2\n");
}
else if (fogMode == GL_EXP2) {
fogMode = GL_LINEAR;
printf ("Fog mode is GL_LINEAR\n");
}
else if (fogMode == GL_LINEAR) {
fogMode = GL_EXP;
printf ("Fog mode is GL_EXP\n");
}
glFogi (GL_FOG_MODE, fogMode);
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutDisplayFunc (display);
glutMainLoop();
return 0;
}
2,雾坐标形式使用雾(自己控制雾方程式)
#include "GLTools.h"
#include "GLShaderManager.h"
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
/*不认识glFogCoordfEXT()的解决方案*/
#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
#define GL_FOG_COORDINATE_EXT 0x8451
PFNGLFOGCOORDFEXTPROC glFogCoordfEXT = NULL;
static GLfloat f1, f2, f3;
static void init(void)
{
GLfloat fogColor[4] = {0.0, 0.25, 0.25, 1.0};
f1 = 1.0f;
f2 = 5.0f;
f3 = 10.0f;
glEnable(GL_FOG);//激活雾效果
glFogi (GL_FOG_MODE, GL_EXP);//设置雾方程式
glFogfv (GL_FOG_COLOR, fogColor);//雾颜色
glFogf (GL_FOG_DENSITY, 0.25);//雾密度
glHint (GL_FOG_HINT, GL_DONT_CARE);//没有偏向
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);//使用雾坐标
glClearColor(0.0, 0.25, 0.25, 1.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f (1.0f, 0.75f, 0.0f);
glBegin (GL_TRIANGLES);
/*使用雾坐标,手动指定每个顶点距离观察点的距离,
不会随观察点的变化而变化*/
glFogCoordfEXT (f1);
glVertex3f (2.0f, -2.0f, 0.0f);
glFogCoordfEXT (f2);
glVertex3f (-2.0f, 0.0f, -5.0f);
glFogCoordfEXT (f3);
glVertex3f (0.0f, 2.0f, -10.0f);
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (45.0, 1.0, 0.25, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -5.0);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'c':
//不使用雾坐标
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
glutPostRedisplay();
break;
case 'C':
//使用雾坐标
glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
glutPostRedisplay();
break;
//改变顶点雾坐标
case '1':
f1 = f1 + 0.25;
glutPostRedisplay();
break;
case '2':
f2 = f2 + 0.25;
glutPostRedisplay();
break;
case '3':
f3 = f3 + 0.25;
glutPostRedisplay();
break;
case '8':
if (f1 > 0.25) {
f1 = f1 - 0.25;
glutPostRedisplay();
}
break;
case '9':
if (f2 > 0.25) {
f2 = f2 - 0.25;
glutPostRedisplay();
}
break;
case '0':
if (f3 > 0.25) {
f3 = f3 - 0.25;
glutPostRedisplay();
}
break;
//前后移动观察点
case 'b':
glMatrixMode (GL_MODELVIEW);
glTranslatef (0.0, 0.0, -0.25);
glutPostRedisplay();
break;
case 'f':
glMatrixMode (GL_MODELVIEW);
glTranslatef (0.0, 0.0, 0.25);
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC) glutGetProcAddress("glFogCoordfEXT");
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutDisplayFunc (display);
glutMainLoop();
return 0;
}