从0开始的OpenGL学习(六)-显示不同的纹理

本文主要解决2个问题:

1、不同格式的图片,如何作为纹理使用(png、bmp)?
2、两张纹理如何进行融合操作,并且通过融合因子去调整显示效果?

一、不同格式的图片,如何作为纹理使用(png、bmp)?

1.1 png格式

不管三七二十一,直接把图片替换掉,看看效果。

直接把图替换为png图片

嗯?这诡异的显示是啥?

第一反应,某些参数设置出错,尤其是glTexImage2D函数。直接瞄准参数GL_RGB,png图片有度的信息,所以格式应该设置为GL_RGBA才对。想明白了,马上修改试试。

修改成GL_RGBA之后

不出所料!

1.2 bmp格式

还是那样,先直接改文件看效果。

换成bmp格式的文件

不对啊,bmp格式不是有透明通道吗?怎么回事?来检查一下图片的属性。

图片属性

哦,原来位深度只有24,也就是只有RGB三个通道了。把格式换回GL_RGB应该没问题了。

换回GL_RGB格式之后的显示

对的,我们分析地没错。那么问题来了,难道我们需要一张张查看图片的属性来设置这个格式吗?这也太复杂了,或者根据图片的后缀确定用什么参数。要是相同后缀的图片有不同格式咋办?

4通道bmp图片

没有开玩笑哦,这样的图片还是很常见的。

仔细看看代码,原来我们在加载图片的时候已经读取出通道数量了,保存在nrChannels变量中。这样就方便多了!我们完全可以根据通道数量来设置格式。简单点,直接用一行代码搞定:

GLint format = nrChannels == 3 ? GL_RGB : GL_RGBA;

然后在调用的时候就可以用format变量了。

glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);

效果图:

效果图

工程源码:http://pan.baidu.com/s/1mh6oQMW

二、两张纹理如何进行融合操作,并且通过融合因子去调整显示效果?

2.1 纹理单元

细心的你可能早就发现了,我们之前的使用纹理采样的时候,并没有对片元着色器中的采样器进行赋值,但显示的效果确实正确的。为什么呢?

这里就要引出一个纹理单元的概念。什么是纹理单元,说实话,笔者也没有找到确切的定义,只知道纹理是通过纹理单元这个东西绑定到OpenGL环境中的。根据笔者的理解,纹理单元应该是OpenGL中内置的关于纹理的一些配置,OpenGL会根据这些配置来操作纹理。在OpenGL中,纹理单元的数量至少有16个,我们可以通过GL_TEXTURE0...GL_TEXTURE15来激活使用。默认激活的是GL_TEXTURE0,所以我们之前的操作都是针对GL_TEXTURE0的。

让我们来激活另一个纹理单元并且对它进行一些操作。

首先,我们用glActiveTexture(GL_TEXTURE1)来激活纹理单元1,使之可操作。

然后,将一个新的纹理ID绑定到这个纹理对象上,我们不妨将这个新ID定义成texture2,调用glBindTexture(GL_TEXTURE_2D,texture2)进行绑定。

接下来,如同之前一样,设置好环绕和过滤方式。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

再接着,我们把图片加载进去,绑定到当前的纹理单元上:

//加载图片
stbi_set_flip_vertically_on_load(true);
unsigned char* data2 = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (data2) {
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
    std::cout << "无法加载问题,请检查代码或资源是否有误。" << std::endl;
stbi_image_free(data2);

最后,非常重要的一个步骤是,我们需要告诉OpenGL着色器采样器和纹理单元之间的对应关系。

//告诉OpenGL哪个采样器属于哪个纹理单元
shader.use();  //着色器要使用之后才能操作
shader.setInt("texture1", 0);  //采样器1对应编号0的纹理单元
shader.setInt("texture2", 1);  //采样器2对应编号1的纹理单元

我们的片元着色器中,也需要做相应的改动:

uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);

}

mix函数是对某个点的纹理进行混合运算,0.2表示该点的颜色20%来自采样器2,80%来自采样器1。好了,编译运行我们的程序。

混合效果

效果很赞,但是还没达到我们想要的状态。别忘了,我们还要通过融合因子对其进行控制!

2.2 融合因子控制

直觉上的,我们需要三步走:

  • 第一步:定义一个全局的融合因子
  • 第二步:点击上下箭头的时候设置这个值
  • 第三步:设置这个融合因子变量值
第一步:定义一个全局的融合因子
float factor = 0.2f;
第二步:点击上下箭头的时候设置这个值

查找上箭头和下箭头的按钮值:GLFW_KEY_UP和GLFW_KEY_DOWN,在处理输入的函数(processInput)中,添加对其的处理。每次按向上箭头时融合因子增加0.01(最大为1.0),每次按向下箭头时融合因子减少0.01,(最小为0.0)。

if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
    factor += 0.01f;
    if (factor > 1.0f)
        factor = 1.0f;
}

if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
    factor -= 0.01f;
    if (factor < 0.0f)
        factor = 0.0f;
}
第三步:设置这个融合因子变量值

在使用了着色器之后,设置其值。

shader.setFloat("factor", factor);

好了,非常简单,但是一定要自己实现才行。编译运行,这下我们可以通过按钮来控制了!(没法放视频,就不截图了。)

整个工程的源码可以在这里找到:http://pan.baidu.com/s/1eRWj7kY

下一篇
目录
上一篇

参考资料:
www.learningopengl.com(非常好的网站,建议学习)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容