Android OpenGL ES详解——纹理:纹理过滤GL_NEAREST和GL_LINEAR的区别

目录

一、概念

1、纹理过滤

2、邻近过滤

3、线性过滤

二、邻近过滤和线性过滤的区别

三、源码下载


一、概念

1、纹理过滤

当纹理被应用到三维物体上时,随着物体表面的形状和相机视角的变化,会导致纹理在渲染过程中出现一些问题,如锯齿状边缘、失真、模糊等。

纹理过滤的作用是解决这些问题,以获得更好的渲染效果。其目的是在纹理被应用到三维模型上时,通过对纹理上的像素进行插值或采样,使得纹理在不同距离和角度下呈现出更平滑、更真实的外观。

纹理坐标不依赖于分辨率(Resolution),它可以是任意浮点值,所以OpenGL需要知道怎样将纹理像素(Texture Pixel,也叫Texel,译注1)映射到纹理坐标。当你有一个很大的物体但是纹理的分辨率很低的时候这就变得很重要了。你可能已经猜到了,OpenGL也有对于纹理过滤(Texture Filtering)的选项。纹理过滤有很多个选项,但是现在我们只讨论最重要的两种:GL_NEAREST和GL_LINEAR。(Texture Pixel也叫Texel,你可以想象你打开一张.jpg格式图片,不断放大你会发现它是由无数像素点组成的,这个点就是纹理像素;注意不要和纹理坐标搞混,纹理坐标是你给模型顶点设置的那个数组,OpenGL以这个顶点的纹理坐标数据去查找纹理图像上的像素,然后进行采样提取纹理像素的颜色。)

2、邻近过滤

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

  • 原理:OpenGL会选择中心点最接近纹理坐标的那个像素作为当前纹理坐标的像素。这种方式不进行任何插值计算,直接采用最邻近像素的颜色值。

  • 特点

    • 快速:由于无需进行复杂的插值计算,GL_NEAREST在性能上通常更优。
    • 锯齿状边缘:由于直接使用单个像素的颜色,放大后的纹理会出现明显的锯齿边缘,尤其是在大幅度缩放或以低分辨率纹理渲染高分辨率物体时。
    • 清晰度:对于小尺寸、像素艺术风格或需要保持锐利边缘的纹理,GL_NEAREST可以保留原始像素的精确颜色,保持图像的清晰度和细节。

3、线性过滤

GL_LINEAR(也叫线性过滤,(Bi)linear Filtering)它会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个纹理像素的颜色对最终的样本颜色的贡献越大。下图中你可以看到返回的颜色是邻近像素的混合色:

  • 原理:基于纹理坐标附近的纹理像素,计算出一个插值,以近似出这些纹理像素之间的颜色。具体来说,当设置为GL_LINEAR时,OpenGL会考虑采样点周围最近的四个纹理像素(一个正方形区域内的像素),并对这四个像素的颜色值进行加权平均,以得到平滑过渡的颜色。对于三维纹理或更高维度的纹理,它会考虑更多的相邻像素并进行更高维的线性插值。

  • 特点

    • 平滑:GL_LINEAR产生的纹理放大效果更加平滑,边缘没有明显的锯齿,视觉效果更为柔和。
    • 模糊:相较于GL_NEAREST,GL_LINEAR可能会引入轻微的模糊,特别是在大幅度缩放时。这种模糊是由于插值过程混合了多个像素的颜色造成的。
    • 适用场景:对于需要平滑过渡、细节丰富、或对视觉质量要求较高的纹理(如照片、自然景观、高清图形等),GL_LINEAR通常能提供更好的视觉效果。

综上所述,GL_NEAREST和GL_LINEAR之所以产生不同的图案效果,是因为它们在处理纹理采样时采用了不同的方法和策略。GL_NEAREST直接采用最邻近像素的颜色值,因此会产生颗粒状图案;而GL_LINEAR则通过考虑附近多个像素的颜色值并进行加权平均,从而得到更平滑的图案效果。

二、邻近过滤和线性过滤的区别

那么这两种纹理过滤方式有怎样的视觉效果呢?让我们看看在一个很大的物体上应用一张低分辨率的纹理会发生什么吧(纹理被放大了,每个纹理像素都能看到):

GL_NEAREST产生了颗粒状的图案,我们能够清晰看到组成纹理的像素,而GL_LINEAR能够产生更平滑的图案,很难看出单个的纹理像素。GL_LINEAR可以产生更真实的输出,但有些开发者更喜欢8-bit风格,所以他们会用GL_NEAREST选项。

当进行放大(Magnify)和缩小(Minify)操作的时候可以设置纹理过滤的选项,比如你可以在纹理被缩小的时候使用邻近过滤,被放大时使用线性过滤。我们需要使用glTexParameter*函数为放大和缩小指定过滤方式。这段代码看起来会和纹理环绕方式的设置很相似:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

三、源码下载

Android OpenGL 图片Texture渲染render 演示demo下载:

https://download.csdn.net/download/github_27263697/89927774

推荐文章

https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/06%20Textures/

https://juejin.cn/post/7369620466397675570

相关推荐
刘好念2 天前
[OpenGL]使用TransformFeedback实现粒子效果
c++·计算机图形学·opengl
吃豆腐长肉4 天前
着色器 (三)
opengl·着色器
吃豆腐长肉4 天前
opengl 着色器 (四)最终章收尾
opengl·着色器
德林恩宝5 天前
WebGPU、WebGL 和 OpenGL/Vulkan对比分析
web·webgl·opengl·webgpu
zaizai10079 天前
LearnOpenGL学习(高级OpenGL -> 高级GLSL,几何着色器,实例化)
opengl
刘好念9 天前
[OpenGL] Transform feedback 介绍以及使用示例
c++·计算机图形学·opengl
爱看书的小沐9 天前
【小沐学GIS】基于C++绘制三维数字地球Earth(OpenGL、glfw、glut、QT)第三期
c++·qt·opengl·earth·osm·三维地球·数字地球
闲暇部落12 天前
OpenGL ES详解——多个纹理实现混叠显示
opengl·纹理叠加
LiQingCode13 天前
OpenTK中文教程——1.7变换
c#·opengl
zaizai100713 天前
LearnOpenGL学习(高级OpenGL --> 帧缓冲,立方体贴图,高级数据)
opengl