OpenGL教程 第41课 体积雾气

OpenGL教程 第41课 体积雾气
这一课我们将介绍体积雾,为了运行这个程序,你的显卡必须支持扩展"GL_EXT_fot_coord"。

#include <windows.h>                               
#include <gl\gl.h>                           
#include <gl\glu.h>                               
#include <math.h>                               

#include "NeHeGL.h"                           

#pragma comment( lib, "opengl32.lib" )                       
#pragma comment( lib, "glu32.lib" )                   

GL_Window*    g_window;                       
Keys*        g_keys;                               
 
 
 下面的代码设置雾的颜色和摄像机在Z方向的深度 
 
 

GLfloat    fogColor[4] = {0.6f, 0.3f, 0.0f, 1.0f};                    // 雾的颜色
GLfloat camz;                                    // 摄像机在Z方向的深度

  
 下面变量GL_FOG_COORDINATE_SOURCE_EXT和GL_FOG_COORDINATE_EXT具有初值,他们在glext.h文件中被定义,这里我们必须感谢Lev Povalahev,它创建了这个文件。如果你想编译你的代码,你必须设置这个值。
为了使用glFogCoordfExt,我们需要定义这个函数的指针,并在程序运行时把它指向显卡中的函数。
 
  

// 使用FogCoordfEXT它需要的变量
#define GL_FOG_COORDINATE_SOURCE_EXT    0x8450                    // 从GLEXT.H得到的值
#define GL_FOG_COORDINATE_EXT        0x8451                   

typedef void (APIENTRY * PFNGLFOGCOORDFEXTPROC) (GLfloat coord);        // 声明雾坐标函数的原形

PFNGLFOGCOORDFEXTPROC glFogCoordfEXT = NULL;                    // 设置雾坐标函数指针为NULL

GLuint    texture[1];                            // 纹理

  
 Nehe的原文介绍了Ipicture的接口,它不是我们这一课的重点,故我还是使用以前的方法加载纹理。 
  
  
 下面的代码用来检测用户的显卡是否支持EXT_fog_coord扩展,这段代码只有在你获得OpenGL渲染描述表后才能调用,否则你将获得一个错误。
首先,我们创建一个字符串,来描述我们需要的扩展。接着我们分配一块内存,用来保存显卡支持的扩展,它可以通过glGetString函数获得。接着我们检测是否含有需要的扩展,如果不存在,则返回false,如存在我们把函数的指针指向这个扩展。 
  

int Extension_Init()
{
    char Extension_Name[] = "EXT_fog_coord";

    // 返回扩展字符串
    char* glextstring=(char *)malloc(strlen((char *)glGetString(GL_EXTENSIONS))+1);
    strcpy (glextstring,(char *)glGetString(GL_EXTENSIONS));       

    if (!strstr(glextstring,Extension_Name))                // 查找是否有我们想要的扩展
        return FALSE;                           

    free(glextstring);                            // 释放分配的内存

    // 获得函数的指针
    glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC) wglGetProcAddress("glFogCoordfEXT");

    return TRUE;
}

  
 下面的代码初始化OpenGL,并设置雾气的参数。 
  

BOOL Initialize (GL_Window* window, Keys* keys)                    //初始化
{
    g_window    = window;                       
    g_keys        = keys;                           

    // 初始化扩展
    if (!Extension_Init())                           
        return FALSE;                           

    if (!BuildTexture("data/wall.bmp", texture[0]))                // 创建纹理
        return FALSE;                           

    glEnable(GL_TEXTURE_2D);                       
    glClearColor (0.0f, 0.0f, 0.0f, 0.5f);                   
    glClearDepth (1.0f);                           
    glDepthFunc (GL_LEQUAL);                       
    glEnable (GL_DEPTH_TEST);                       
    glShadeModel (GL_SMOOTH);                       
    glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);           
  
 下面的代码设置雾气的属性
最后一个设置为雾气基于顶点的坐标,这运行我们把雾气放置在场景中的任意地方。
 
  

    glEnable(GL_FOG);                           
    glFogi(GL_FOG_MODE, GL_LINEAR);                       
    glFogfv(GL_FOG_COLOR, fogColor);                   
    glFogf(GL_FOG_START,  1.0f);                       
    glFogf(GL_FOG_END,    0.0f);                       
    glHint(GL_FOG_HINT, GL_NICEST);                       
    glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);        //设置雾气是基于顶点的坐标的

    camz =    -19.0f;                               

    return TRUE;                           
}
  
 下面的代码绘制具体的场景 
  

void Draw (void)
{
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);           
    glLoadIdentity ();                           

    glTranslatef(0.0f, 0.0f, camz);                       

  
 下面的代码绘制四边形组成的墙,并设置每个顶点的纹理坐标和雾坐标 
  

    glBegin(GL_QUADS);                            //后墙
         glFogCoordfEXT(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-15.0f);
    glEnd();

    glBegin(GL_QUADS);                            // 地面
         glFogCoordfEXT(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f,-2.5f, 15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f,-2.5f, 15.0f);
    glEnd();

    glBegin(GL_QUADS);                            // 天花板
        glFogCoordfEXT(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f, 2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f, 2.5f,-15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f, 15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, 15.0f);
    glEnd();

    glBegin(GL_QUADS);                            // 右墙
        glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 2.5f,-2.5f, 15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 2.5f, 2.5f, 15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-15.0f);
    glEnd();

    glBegin(GL_QUADS);                            // 左墙
         glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f, 15.0f);
        glFogCoordfEXT(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, 15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-15.0f);
        glFogCoordfEXT(0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-15.0f);
    glEnd();

    glFlush ();                                                                                                  
}

  
 希望你喜欢这一课,如果你愿意的话创建更漂亮的体积雾吧。

 
 

你可能感兴趣的:(OpenGL教程 第41课 体积雾气)