纹理
来源: 哔哩哔哩      时间:2023-08-05 22:38:09

我们使用纹理为图形增加更多的细节。

纹理坐标在x和y轴上,范围为0到1之间。使用纹理坐标获取纹理颜色叫做采样(Sampling)。纹理坐标始于(0, 0),也就是纹理图片的左下角,终于(1, 1),即纹理图片的右上角。


(相关资料图)

创建纹理

创建纹理和之前创建OpenGL对象的方式一样。

GL_TEXTURE_2D是我们使用的纹理类型。

纹理环绕方式

创建纹理后,我们需要设置纹理环绕方式。纹理环绕方式用来控制纹理在物体表面上的重复、拉伸或镜像效果。以下是常见的纹理环绕方式:

GL_REPEAT(默认):纹理在物体表面上重复平铺。

GL_MIRRORED_REPEAT:和GL_REPEAT一样,但在每次重复时,纹理会进行镜像翻转。

GL_CLAMP_TO_EDGE:纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。

GL_CLAMP_TO_BORDER:超出范围的纹理坐标会使用指定的边界颜色来采样。

我们一般使用函数glTexParameteri()设置纹理环绕方式。

第一个参数指定了纹理类型,譬如我们使用的是2D纹理,为GL_TEXTURE_2D。第二个参数为设置的选项。第三个参数是纹理环绕方式。

下面设置了水平方向和垂直方向的环绕方式:

GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_T分别代表纹理坐标的水平和垂直方向。

加载纹理

我们使用stb_image库来加载图像。

函数stbi_load()可以将图片加载到内存中:

filename是要加载的图像文件的文件名。

width是一个指向整数的指针,用于存储图像的宽度。

height用于存储图像的高度。

channels用于存储图像的通道数。

desired_channels是期望的输出通道数,通常可以设置为0来保持原始图像通道数。

注意,由于OpenGL要求y轴0坐标在图片的底部,但是通常图片的y轴的0坐标通常在顶部。因此我们加载的纹理是上下颠倒的。我们需要在加载纹理之前调用翻转y轴的函数:

生成纹理

现在我们使用之前创建的纹理对象和加载进来的图片生成一个纹理。

调用函数glTexImage2D()

target: 纹理目标,通常为GL_TEXTURE_2D

level: 纹理级别,通常为0,表示基本级别。

internalFormat: 指定纹理的内部格式,比如GL_RGB

width: 纹理的宽度。

height: 纹理的高度。

border: 边框的宽度,通常为0。

format: 传入数据的格式,比如GL_RGB。

type: 传入数据的数据类型。

data: 指向图像数据的指针。

接下来我们还需要调用glGenerateMipmap(GL_TEXTURE_2D)。这个函数的作用我们暂且忽略,之后会提及。

生成纹理后,还应及时释放图像的内存。

下面是生成一个纹理的基本流程:

应用纹理

首先更新顶点数据,增加纹理坐标。

接着配置顶点属性。之后我们要更新着色器代码。

顶点着色器:我们把纹理坐标发送到顶点着色器中,再从顶点着色器发送到片段着色器。

片段着色器:现在片段着色器最终输出的颜色应是对纹理采样得到的颜色。

函数texture()在GLSL中用于从纹理中采样颜色值。

sampler是一个二维纹理采样器类型,用于指定从哪个纹理单元中进行采样。可以将纹理单元视为存储纹理图像的位置。coordinates是一个二维向量,表示从纹理中采样的坐标。texture()会根据指定的纹理采样器和坐标,在纹理图像上找到对应位置的颜色值,并返回一个vec4类型的颜色值。所以我们要在片段着色器中声明一个采样器变量sampler。

虽然sampler是一个uniform全局变量,但我们并不需要对其赋值。原因之后会提及。

到此我们已经可以成功把一个纹理应用在图形上了:

在片段着色器中,我们还可以把纹理和颜色进行混合,只需把二者相乘:

这是混合后的效果:

标签:
最新推荐 更多 +

广告

X 关闭

广告

X 关闭