纹理坐标:
float texCoords[] = {
0.0f, 0.0f, // 左下角
1.0f, 0.0f, // 右下角
0.5f, 1.0f // 上中
};
需要自己告诉OpenGL该怎样对纹理采样。
每个选项都可以使用glTexParameter*
函数对单独的一个坐标轴设置(s、t(如果是使用3D纹理那么还有一个r)它们和x、y、z是等价的):
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
GL_CLAMP_TO_BORDER:
float borderColor[] = {
1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
纹理过滤
将纹理像素(Texel)映射到纹理坐标——纹理过滤,有很多个选项,最重要的两种:GL_NEAREST(默认,临近过滤)和GL_LINEAR(线性过滤)。
放大(Magnify)和缩小(Minify)操作的时候可以设置纹理过滤的选项,使用glTexParameter*
函数为放大和缩小指定过滤方式。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
MIPMAP,多级渐远纹理
注:games101中讲过
切换层数时的过滤方式:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
具体原理games中有详细解释。
加载与创建纹理
此处需要加一个头文件,按照教程操作完后记得包含一下目录,不然会发生打不开源文件.h的情况
使用stb_image.h加载图片,stbi_load
函数:
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
接受文件的位置作为输入。会用图像的宽度、高度和颜色通道的个数填充后面三个变量。
另外一点要注意的,就是传入图片的时候直接把图片放在文件里面,然后直接输入文件路径就可以。用FileSystem::getPath
会报错
生成纹理
创建:
unsigned int texture;
glGenTextures(1, &texture);
绑定:
glBindTexture(GL_TEXTURE_2D, texture);
载入纹理:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
参2:纹理指定多级渐远纹理的级别,0是基本级别。
参3:纹理储存格式
参6:总是被设为0(历史遗留问题)。
参7、8:定义了源图的格式和数据类型。
参9:正的图像数据。
释放内存:
stbi_image_free(data);
项目整体代码及注释如下:
1)顶点着色器代码及注释:
#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;
}
2)片段着色器如下:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = texture(ourTexture, TexCoord);
//使用GLSL内建的texture函数来采样纹理的颜色,
//使用之前设置的纹理参数对相应的颜色值进行采样。
//这个片段着色器的输出就是纹理的(插值)纹理坐标上的(过滤后的)颜色。
}
3)箱子.cpp代码及注释:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <shader.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main()
{
glfwInit(); //窗口常规操作
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowH