1、雾根据混合因子把雾颜色与源片断的颜色进行混合。
雾方程有三个:一次指数型、二次指数型、线性型
使用glFog*设置雾属性
2、RGBA模式下,按照下面方式使用雾因子f计算最终的雾颜色:
C = fCi + (1-f)Cf;
其中Ci表示源片断的RGBA值,Cf表示用GL_FOG_COLOR分配的雾颜色值。
3、默认情况下,雾方程式中的雾坐标z,是根据观察点和片断的距离自动计算产生的,但是也可以为每个顶点指定雾坐标,z值应该是正的,表示视觉坐标的距离,应该避免使用负值来表示雾坐标,因为使用负的雾坐标可能会计算出奇怪的颜色。
在几何图元的内部,雾坐标可能由每个片断插值而得。
如果使用”显示雾坐标“,即通过glFogi( GL_FOG_COORD_SRC, x);其中x可以是GL_FOG_COORD 或GL_FOG_COORDINATE_EXT, 在前后移动观察点时,并不会转换雾坐标,顶点的颜色不受影响;
如果不使用显式雾坐标,即通过glFogi( GL_FOG_COORD_SRC, y); 其中y可以是GL_FRAGMENT_DEPTH或者GL_FRAGMENT_DEPTH_EXT,在移动观察点时会极大地影响由计算所产生的雾颜色。
测试程序1:雾效果
#include "stdafx.h"
#include <windows.h>
#include <glew.h>
#include <freeglut.h>
#pragma comment(lib, "glew32d.lib")
#pragma comment(lib, "freeglut.lib")
static GLint fogMode;
void init()
{
GLfloat position[] = { 0.5, 0.5, 3.0, 0.0 };
glEnable( GL_DEPTH_TEST );
glLightfv( GL_LIGHT0, GL_POSITION, position );
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.5); //设置雾浓度
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()
{
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)
{
switch( key )
{
case 'f':
case 'F':
if( fogMode == GL_EXP )
{
fogMode = GL_EXP2;
printf( "Fog mode id 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 'Q':
exit( 0 );
break;
default:
break;
}
}
int main(int argc, char* argv[])
{
glutInit( &argc, argv);
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH );
glutInitWindowSize( 500, 500);
glutInitWindowPosition( 100, 100);
glutCreateWindow( argv[0]);
glewInit();
init();
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
测试程序2:雾坐标
#include "stdafx.h"
#include <windows.h>
#include <glew.h>
#include <freeglut.h>
#pragma comment(lib, "glew32d.lib")
#pragma comment(lib, "freeglut.lib")
static GLint fogMode;
static GLfloat f1,f2,f3;
void init()
{
GLfloat fogColor[4] = {0.0, 0.25, 0.25, 1.0};
f1 = 1.0f;
f2 = 5.0f;
f3 = 10.0f;
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.5); //设置雾浓度
glHint( GL_FOG_HINT, GL_DONT_CARE ); //设置雾,显示质量优先? 还是速度优先? 还是不关心?
glFogi( GL_FOG_COORD_SRC, GL_FOG_COORD );
}
glClearColor( 0.0, 0.25, 0.25, 1.0);
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f( 1.0f, 0.75f, 0.0f);
glBegin( GL_TRIANGLES );
glFogCoordf( f1 );
glVertex3f( 2.0f, -2.0f, 0.0f);
glFogCoordf( f2 );
glVertex3f( -2.0f, 0.0f, -5.0f);
glFogCoordf( f3);
glVertex3f( 0.0f, 2.0f, -10.0f);
glEnd();
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)
{
switch( key )
{
case 'c':
glFogi( GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH/*GL_FRAGMENT_DEPTH_EXT*/ );
glutPostRedisplay();
break;
case 'C':
glFogi( GL_FOG_COORD_SRC, /*GL_FOG_COORD*/ 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( 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 'Q':
exit( 0 );
break;
default:
break;
}
}
int main(int argc, char* argv[])
{
glutInit( &argc, argv);
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH );
glutInitWindowSize( 500, 500);
glutInitWindowPosition( 100, 100);
glutCreateWindow( argv[0]);
glewInit();
init();
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}