OpenGLut开发入门系列教程9:迷雾

系列教程索引:OpenGLut开发入门系列教程索引

上一篇:OpenGLut开发入门系列教程8:光照

和灯光类似。迷雾有颜色,有角度等等

opengl三维世界坐标系为:

3d

  • OpenGL坐标系(物体、世界、照相机坐标系)属于右手坐标系
  • 设备坐标系使用的是左手坐标系

我们之前开发的代码中一般z轴部分为负值,也就是说,我们看的视角是从z轴的+方向看向-方法。迷雾按照我们看的方向投射在我们绘制的物体上。

首先函数基本的架构是:

flow

在main函数中glut*Func()的参数为回调函数,需要在main函数外独立实现。

重要的是四个回调函数:

  • initGL,初始化函数
  • reshapeGL,尺寸调整函数,当窗口的尺寸发生变化时调用此函数重新绘图
  • keyboard,捕获键盘输入并处理
  • displayGL,将想要显示的图像绘制出来的函数

其他函数说明见OpenGL函数功能说明系列

加载纹理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//加载纹理
void loadGLTexture(){
int w,h,c;//图片的宽度高度和通道数

unsigned char *data=stbi_load("crate.bmp",&w,&h,&c,0);

//创建纹理
glGenTextures(3,&texture[0]);

//纹理1-低质量缩放
glBindTexture(GL_TEXTURE_2D,texture[0]);//绑定纹理

//纹理过滤
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

//二位纹理,细节等级,RGB3组件,宽,高,边框,rgb数据,无符号整数,数据
if(c==3){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,data);
}else if(c==4){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
}

//纹理2-线性缩放
glBindTexture(GL_TEXTURE_2D,texture[1]);//绑定纹理

//纹理过滤
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

//二位纹理,细节等级,RGB3组件,宽,高,边框,rgb数据,无符号整数,数据
if(c==3){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,data);
}else if(c==4){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
}

//纹理3-映射缩放
glBindTexture(GL_TEXTURE_2D,texture[2]);//绑定纹理

//纹理过滤
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);

//二位纹理,细节等级,RGB3组件,宽,高,边框,rgb数据,无符号整数,数据
if(c==3){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,data);
}else if(c==4){
glTexImage2D(GL_TEXTURE_2D, 0, 3,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
}

//二位纹理,RGB3颜色,宽,高,Rgb边框值,rgb数据,无符号整数,数据
if(c==3){
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,w,h,GL_RGB,GL_UNSIGNED_BYTE,data);
}else if(c==4){
gluBuild2DMipmaps(GL_TEXTURE_2D, 3,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);
}
}

和上一篇的一样,就是在上一篇的基础上改的。

流程上还是获取数据、创建纹理、绑定纹理、生成纹理。

设置迷雾

在初始化函数中设置雾的颜色、位置。

1
2
3
4
5
6
7
glFogi(GL_FOG_MODE, fogMode[fogfilter]);//雾化模式
glFogfv(GL_FOG_COLOR, fogColor);//设置雾化颜色
glFogf(GL_FOG_DENSITY,0.35f);//雾的密度
glHint(GL_FOG_HINT,GL_DONT_CARE);//雾化提示值
glFogf(GL_FOG_START,1.0f);//开始深度
glFogf(GL_FOG_END,5.0f);//结束深度
glEnable(GL_FOG);//启用雾化

绘制图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
glBindTexture(GL_TEXTURE_2D,texture[filter]);//选择纹理

glBegin(GL_QUADS);//开始绘制
// Front Face (note that the texture's corners have to match the quad's corners)
glNormal3f(0.0f,0.0f,1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad

// Back Face
glNormal3f(0.0f,0.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad

// Top Face
glNormal3f(0.0f,1.0f,0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad

// Bottom Face
glNormal3f(0.0f,-1.0f,0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad

// Right face
glNormal3f(1.0f,0.0f,0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad

// Left Face
glNormal3f(-1.0f,0.0f,0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glEnd();//正方形绘制结束

绘图部分和之前的纹理绘图一样。

键盘捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

//如果有按键按下调用此函数
void keyboard(unsigned char key, int x, int y)
{
usleep(100);//稍微延时以免干扰

switch(key){
case ESCAPE:
glutDestroyWindow(window); //销毁窗口
exit(0);//正常退出程序
break;
case ' ':
std::cout<<"Fog is: "<<fogstatus<<std::endl;
fogstatus=fogstatus?0:1; //
std::cout<<"Fog is: "<<fogstatus<<std::endl;
if(!fogstatus){
glDisable(GL_FOG);
}else{
glEnable(GL_FOG);
}
break;
case 70:
case 102:
std::cout<<"Filter is: "<<filter<<std::endl;
filter+=1;
if(filter>2){
filter=0;
}
std::cout<<"Filter is: "<<filter<<" now."<<std::endl;
break;
case 71:
case 103:
fogfilter+=1;
if(fogfilter>2){
fogfilter=0;
}
glFogi(GL_FOG_MODE, fogMode[fogfilter]);
break;
default:
break;
}
}

要想捕获键盘输入,就得知道键盘输入是什么。

ascii

想要捕获什么就在keyboard函数中处理什么。

使用空格来控制迷雾效果是否启动,F/f控制纹理过滤规则,G/g控制迷雾类型。

为了查看迷雾颜色效果,我们在此把窗口的背景色也设置为迷雾的颜色。

未加载纹理效果

no texture

加载纹理后

texture

取消迷雾效果后

no fog

完整源码在OpenGL_Freshman下的OpenGLut的9中。

下一篇:OpenGLut开发入门系列教程10:混合