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

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

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

本文介绍混合效果。

混合(blend)所谓的混色,就是将当前要绘制的物体的颜色和颜色缓冲区中已经绘制的颜色进行混合,最终决定了当前物体的颜色。

就好像贴窗花一样,我们可以透过窗花透明的部分看到墙里面的东西。

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

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

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

设置迷雾

在初始化函数中设置混色的颜色。颜色是直接作用在纹理和视角之间,要想实现混合,颜色必须要有透明度即RGBA中的A。而且0表示完全透明,1表示完全不透明,此时混色功能就没用了。

测试用彩色图片,如果混色使用彩色会盖住纹理,所有混色为白色,透明度为50%。

1
2
3
//设置混合
glBlendFunc(GL_SRC_ALPHA,GL_ONE);//设置混合功能
glColor4f(1.0f,1.0f,1.0f,0.5f);

绘制图像

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
43
44
45
46
47
48

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

switch(key){
case ESCAPE:
glutDestroyWindow(window); //销毁窗口
exit(0);//正常退出程序
break;
case 76:
case 108://调整光照
std::cout<<"Light is: "<<light<<std::endl;
light = light?0:1;
std::cout<<"Light is: "<<light<<" now"<<std::endl;
if(!light){
glDisable(GL_LIGHTING);
}else{
glEnable(GL_LIGHTING);
}
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 98:
case 130:
std::cout<<"Blend is: "<<blend<<std::endl;
blend = blend?0:1;
std::cout<<"Blend is: "<<blend<<" now"<<std::endl;
if(!blend){
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}else{
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
break;
default:
break;
}
}

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

ascii

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

使用B/b来控制混合效果是否启动,F/f控制纹理过滤规则。

未加载纹理效果

no texture

加载纹理后

texture

开启混合后

texture

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

下一篇:OpenGLut开发入门系列教程11:烟火晚会


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!