3 Texture

文本统计:约 435 个字 • 22 行代码

给物体进行纹理贴图的过程分为生成纹理与应用纹理

生成纹理的过程与前面的基本相似

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// 为当前绑定的纹理对象设置环绕、过滤方式
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 加载并生成纹理
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);

关于纹理的环绕方式与过滤方式直接看文章即可

然后应用纹理,需要纹理的顶点坐标以及相应的纹理对象。

相应的纹理坐标在顶点着色器中被导入

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor;
    TexCoord = aTexCoord;
}

纹理对象在片段着色器中被导入

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D texture1;
uniform sampler2D texture2;

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

那么纹理对象是怎么被导入到片段着色器的呢,这里用纹理单元的例子。当我们需要导入多个纹理的时候,就需要用到纹理单元,分别是 GL_TEXTURE0GL_TEXTURE15,每当我需要导入纹理对象的时候,先将相应的纹理单元激活,然后绑定相应纹理。当然在执行这些操作之前还需要告诉OpenGL每个着色器采样器属于哪个纹理单元。所以具体的流程如下所示

//设置采样器属于哪个纹理单元
ourShader.use();
ourShader.setInt("texture1",0);
ourShader.setInt("texture2",1);
//绑定相应的纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);

Warning

为OpenGL要求y轴0.0坐标是在图片的底部的,但是图片的y轴0.0坐标通常在顶部。很幸运,stb_image.h能够在图像加载时帮助我们翻转y轴,只需要在加载任何图像前加入以下语句即可:

stbi_set_flip_vertically_on_load(true);

评论区

对你有帮助的话请给我个赞和 star => GitHub stars
欢迎跟我探讨!!!