OpenGL入门12——雾

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


你可能感兴趣的:(OpenGL入门12——雾)