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; }
#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; }