OpenGL 纹理(Textures)

Reading time ~1 minute

纹理

我们可以为每个顶点使用颜色来增加图形的细节,从而创建出有趣的图像。但是,如果想让图形看起来更真实我们就必须有足够多的顶点,从而指定足够多的颜色。这将会产生很多额外开销,因为每个模型都会需求更多的顶点和顶点颜色。

更多的时候是使用纹理。纹理是一个2D图片(也有1D和3D),它用来添加物体的细节。因为我们可以在一张图片上插入足够多的细节,这样物体就会拥有很多细节而不用增加额外的顶点。

纹理坐标

为了能够把纹理映射到三角形上,我们需要指定三角形的每个顶点各自对应纹理的哪个部分。这样每个顶点就会有一个纹理坐标(Texture Coordinate),它指明从纹理图像的哪个地方采样(采集像素颜色)。之后在所有的其他的片段上进行片段插值(Fragment Interpolation)。

纹理坐标是x和y轴上0到1之间的范围(注意我们使用的是2D纹理图片)。使用纹理坐标获取纹理颜色叫做采样(Sampling)。纹理坐标起始于(0,0)也就是纹理图片的左下角,终结于纹理图片的右上角(1,1)。下面的图片展示了我们是如何把纹理坐标映射到三角形上的。

我们为三角形准备了3个纹理坐标点。我们只要传递这三个纹理坐标给顶点着色器就行了,接着片段着色器会为每个片段生成纹理坐标的插值。 纹理采样有几种不同的插值方式。我们需要自己告诉OpenGL在纹理中采用哪种采样方式。

纹理环绕方式(Texture Wrapping)

纹理坐标通常的范围是从(0,0)到(1,1),如果我们把纹理坐标设置为范围以外,OpenGL默认的行为是重复这个纹理图像(我们简单地忽略浮点纹理坐标的整数部分),但OpenGL提供了更多的选择:

纹理环绕方式

效果如下:

纹理环绕方式的效果

纹理过滤(Texture Filtering)

纹理坐标不依赖于解析度,它可以是任何浮点数值,这样OpenGL需要描述出哪个纹理像素(Texture Pixel,也叫Texel)对应哪个纹理坐标。当你有一个很大的物体但是纹理解析度很低的时候这就变得很重要了。OpenGL也有一个叫做纹理过滤的选项。有多种不同的选项可用,但是现在我们只讨论最重要的两种:GL_NEAREST和GL_LINEAR。

GL_NEAREST(Nearest Neighbor Filtering,邻近过滤)是一种OpenGL默认的纹理过滤方式。当设置为GL_NEAREST的时候,OpenGL选择最接近纹理坐标中心点的那个像素。下图你会看到四个像素,加号代表纹理坐标。左上角的纹理像素是距离纹理坐标最近的那个,这样它就会选择这个作为采样颜色:

GL_NEAREST过滤方式

GL_LINEAR((Bi)linear Filtering,线性过滤)它会从纹理坐标的临近纹理像素进行计算,返回一个多个纹理像素的近似值。一个纹理像素距离纹理坐标越近,那么这个纹理像素对最终的采样颜色的影响越大。下面你会看到临近像素返回的混合颜色:

GL_LINEAR过滤方式

不同的纹理过滤方式有怎样的视觉效果呢?让我们看看当在一个很大的物体上应用一张地解析度的纹理会发生什么吧(纹理被放大了,纹理像素也能看到):

两种过滤方式的效果

可以看到,因为GL_NEAREST只选择一个临近的像素,所以产生了许多小格子,能够清晰看到纹理由像素组成。而GL_LINEAR因为进行了计算,会产生出更平滑的样式,看不出纹理像素。

纹理过滤可以为放大和缩小设置不同的选项,这样你可以在纹理被缩小的时候使用最临近过滤,被放大时使用线性过滤。

多级渐远纹理(Mipmaps)

想象一下,如果我们在一个有着上千物体的大房间,每个物体上都有纹理。距离观察者远的与距离近的物体的纹理的解析度是相同的。由于远处的物体可能只产生很少的片段,OpenGL从高解析度纹理中为这些片段获取正确的颜色值就很困难。这是因为它不得不为一个纹理跨度很大的片段取纹理颜色。在小物体上这会产生人工感,更不用说在小物体上使用高解析度纹理浪费内存的问题了。

OpenGL使用一种叫做 多级渐远纹理(Mipmap) 的概念解决这个问题,大概来说就是一系列纹理,后面的一个纹理是前一个的二分之一。多级渐远纹理背后的思想很简单:距离观察者更远距离的一段阈值,OpenGL会把最适合这个距离的物体的不同的多级渐远纹理纹理应用其上。由于距离远,解析度不高也不会被使用者注意到。同时,多级渐远纹理另一优点是执行效率不错。多级渐远纹理纹理:

Mipmap示例

OpenGL渲染的时候,两个不同级别的多级渐远纹理之间会产生不真实感的生硬的边界。就像普通的纹理过滤一样,也可以在两个不同多级渐远纹理级别之间使用NEAREST和LINEAR过滤。指定不同多级渐远纹理级别之间的过滤方式可以使用下面四种选项代替原来的过滤方式:


参考: LearnOpenGL-CN 纹理(Textures)

Scriptable Objects 及 游戏架构

Scriptable Objects 相关介绍,及基于其的游戏架构技术 Continue reading

AssetBundle 最佳实践

Published on January 29, 2019

AssetBundle 基础总结

Published on January 27, 2019