OpenGL learning starting from 0 (f) - display a different texture (glActiveTexture activate different default texture unit to bind different textures)

Original link: https://www.jianshu.com/p/cffca3e3f872

glActiveTexture activate different texture unit

First, we use glActiveTexture(GL_TEXTURE1)to activate the texture unit 1, so as to be operable.

Then, a new texture ID bound to the texture object, we may wish to define this new ID into texture2, calls glBindTexture(GL_TEXTURE_2D,texture2)for binding.

 

OpenGL learning starting from 0 (f) - display a different texture

0.0252017.10.11 21:06:50 1369 read 4984 words

In this paper, to solve two problems:

1, different format images, how to use as a texture (png, bmp)?
2, how two texture fusion procedures, and to adjust the display through the integration factor?

A different format images, how to use as a texture (png, bmp)?

1.1 png format

Just-do, directly replace the picture, look at the results.

Replace directly to the map png picture

 

Ok? This display is strange what?

A first reaction, certain parameters setting error, in particular glTexImage2Dfunction. Direct targeting parameters GL_RGB, png picture of the information, so the format should be set to GL_RGBA son. Want to see, immediately try to modify.

After the modified GL_RGBA

 

As expected!

1.2 bmp format

Or as the first change direct file to see results.

Bmp file formats into

 

Not ah, bmp format is not transparent channel it? what happened? To check the properties of the picture.

Image properties

 

Oh, a bit depth of only 24, which is only three channels of RGB. The format in exchange for GL_RGB should be no problem.

After the display format of exchange GL_RGB

 

Right, we analyze the right. So the question is, do we need to see a picture of the picture property to set the file? This is too complicated, or determine what parameters according to the suffix of the picture. If the same suffix pictures have different formats we supposed to?

4-channel bmp picture

Oh, no kidding, so that the picture is still very common.

仔细看看代码,原来我们在加载图片的时候已经读取出通道数量了,保存在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

下一篇

Guess you like

Origin blog.csdn.net/u010029439/article/details/100921072