【转】OpenGL随笔(1)—— mipmap 详解
注:本文使用的所有 OpenGL 函数来自 OpenGL 4.5,优先使用 DSA。
使用 mipmap 时,OpenGL 根据被映射对象的大小(单位是像素),自动决定使用纹理图的哪个分辨率级别。mipmap 表示着纹理的层次细节(LOD),随着对象图像变小,使用纹理图的大小将减少。mipmap 需要一些额外的计算和纹理存储空间(大概三分之一),但这些消耗是值得的,如果不使用 mipmap ,那么映射到更小图像上的纹理将随着物体移动而闪烁。
OpenGL 的 mipmap 省去了纹素大小和多边形大小的缩放因子 λ 的详细讨论,不更改则使用默认值。下文将使用默认的 mipmap 参数,最后会讨论控制 λ 的细节。
参数 GL_TEXTURE_MIN_FILTER 控制在 mipmap 级数大于 0 时如何重建纹素。这个参数共有 6 个设置。前两个与用于放大的相同,GL_NEAREST 和 GL_LINEAR。选择这两个参数会禁用 mipmap,OpenGL 将使用纹理的基数级(级数0)。其他四个模式启用 mipmap,并控制着 mipmap 的使用。这四个值分别是 GL_NEAREST_MIPMAP_NEAREST、GL_LINEAR_MIPMAP_NEAREST、GL_NEAREST_MIPMAP_LINEAR、GL_LINEAR_MIPMAP_LINEAR。名字结构的第一部分控制纹素的构造,表示当前采用纹理的构造方式;第二部分控制 mipmap 级之间采样模式,NEAREST 表示只使用最近的 mipmap 级,LINEAR 则表示最近的两个 mipmap 线性插值。
为了使用 mipmap,必须提供纹理在最大尺寸和 1x1 图之间的所有大小是 2 的幂的纹理级别。如果不想使用 mipmap 到 1x1 纹理的所有变化,可以将 GL_TEXTURE_MAX_LEVEL 的值设置为提供的最大级数,并且 OpenGL 不会考虑更进一步的级别。如果纹理最高级别的分辨率不是正方形,那么一个维度将比另外一个首先到达大小为 1 的纹素。在这种情况下,将继续对这个维度创建新的层级,直到两个维度到达 1x1 的形式为止。例如,如果最高分辨率是 64x16,则必须提供大小 32x8,16x4,8x2,4x1,2x1 和 1x1。mipmap 小图纹素的获取对应于大图 4 个纹素的加权平均。
需要特别注意的一点是 glTextureStorage* 生成的纹理空间是不可变的,也就是说不可以使用 glGenerateTextureMipmap 来自动生成函数,而只能用 glTextrueSubImage2D 来手动载入各级纹理;试图让 OpenGL 自动生成 mipmap,请使用 glTextureImage*。
OpenGL 提供一个函数,其在应用程序的控制下为纹理自动生成所有的 mipmap—— glGenerateTextureMipmap。在 OpenGL 实现中,它提供了通过采样高分辨率图像来生成更低分辨率图像的一个机制。这通常使用着色器和纹理滤波硬件来实现。这个技术通常被设计用于性能多于质量,并且在不同的实现之间有变化。如果想要高质量的结果,最好自己生成和提供 mipmap 图像。如果需要快速生成 mipmap 链并且对获得的任何结果都满意,可以使用 glGenerateTextureMipmap 函数。
计算特定像素的纹理级别时,其结果取决于纹理图像和纹理映射的多边形大小比例因子。我们称这个比例因子为 ρ,再定义第二个值 λ,且 λ=log2ρ+lodbias(因为纹理图像可以是多维的,所以声明 ρ 是所有维的最大比例因子是很重要)。
lodbias 是采样器的细节层次偏移,在 glSamplerParameteri 中设置参数为 GL_TEXTURE_LOD_BIAS 来修改它,从而修改 λ。默认 lodbias=0.0,如果 λ≤0.0,意味着纹素小于像素,所以使用放滤波器。如果 λ>0.0,则使用缩小滤波器。如果缩小滤波器使用 mipmap,那么 λ 是 mipmap 级别。
例如,如果纹理图像是 64x64 像素,多边形大小是 32x32 像素,那么 ρ=2.0(单个维度的比值),则 λ=1.0。如果纹理图像是 64x32 纹素,并且多边形尺寸是 8x16 像素,那么 ρ=8.0(x 比例是 8.0,y 比例是 2.0,则使用最大值),因此 λ=3.0。计算 λ 和 ρ 的方程如下:
Mipmap 级别的计算可以进一步通过一些采样器参数来控制。GL_TEXTURE_LOD_BIAS 可以用来偏移 λ。计算 λ 后,可以截取边界到用户设置的范围。这通过参数 GL_TEXTURE_MIN_LOD 和 GL_TEXTURE_MAX_LOD 给出,可以通过函数 glSamplerParameterf 或 glTextureParameterf 来设置。GL_TEXTURE_MIN_LOD 和 GL_TEXTURE_MAX_LOD 默认值分别为 -1000.0 和 1000.0。GL_TEXTURE_MIN_LOD 和 GL_TEXTURE_MAX_LOD 在下式中分别用 lodmin 和 lodmax 来表示:
除了计算 λ 时控制 lodmin、lodmax 和 λbase 的参数,通过 GL_TEXTURE_BASE_LEVEL 和 GL_TEXTURE_MAX_LEVEL 参数来提供 mipmap 选择 level 的进一步控制,这些参数使用 glSamplerParameteri 来设置。GL_TEXTURE_BASE_LEVEL 设置被采样的最低 mipmap 级别(最高分辨率), GL_TEXTURE_MAX_LEVEL 设置被采样的最高 mipmap 级别(最低分辨率),用来限制采样级别范围。
GL_TEXTURE_BASE_LEVEL 的一个潜在的用处是纹理流。使用纹理流时,完整纹理对象的存储使用函数(例如 glTextureStorage2D)分配但没有加载初始数据。随着应用程序的运行,新对象进入视野,加载从最低到最高分辨率的纹理数据。即使还没有加载完整的纹理,但为了保证有意义的东西显示给用户,可以设置 GL_TEXTURE_BASE_LEVEL 的值为已经加载的最高分辨率 mipmap 级别。使用这个方法,随着加载越来越多的纹理数据,屏幕上的图像将获得越来越高的逼真度。
【转】OpenGL随笔(1)—— mipmap 详解的更多相关文章
- OpenGL ES一些函数详解(一)
glLoadIdentity和glMultMatrix glLoadIdentity的作用是将当前模型视图矩阵转换为单位矩阵(行数和列数相同的矩阵,并且矩阵的左上角至右下角的连线上的元素都为1,其 ...
- Android随笔之——PackageManager详解
参考:http://www.cnblogs.com/xingfuzzhd/p/3374504.html 今天要讲的是PackageManager.Android系统为我们提供了很多服务管理的类,包括A ...
- [转载] Android随笔之——PackageManager详解
本文转载自: http://www.cnblogs.com/travellife/p/3932823.html 参考:http://www.cnblogs.com/xingfuzzhd/p/33745 ...
- OpenGL ES2.0入门详解
引自:http://blog.csdn.net/wangyuchun_799/article/details/7736928 1.决定你要支持的OpenGL ES的版本.目前,OpenGL ES包含 ...
- 【转】Android随笔之——PackageManager详解
参考:http://www.cnblogs.com/xingfuzzhd/p/3374504.html 今天要讲的是PackageManager.Android系统为我们提供了很多服务管理的类,包括A ...
- 【OpenGL】法线变换详解(Normal Transform)[转]
http://blog.csdn.net/xiajun07061225/article/details/7762711 在图形学中,同样的一个模型视图变换矩阵可以用来变换点.线.多边形以及其它几何体, ...
- Android随笔之——闹钟制作铺垫之AlarmManager详解
说实话,之前写的两篇博客Android广播机制Broadcast详解.Android时间.日期相关类和方法以及现在要写的,都算是为之后要写的闹钟应用做铺垫,有兴趣的话,大家可以去看看前两篇博客. 一. ...
- OpenGL的glTranslatef平移变换函数详解
OpenGL的glTranslatef平移变换函数详解 glTranslated()和glTranslatef()这两个函数是定义一个平移矩阵,该矩阵与当前矩阵相乘,使后续的图形进行平移变换. 我们先 ...
- OpenGL的glRotatef旋转变换函数详解
OpenGL的glRotatef旋转变换函数详解 先看一下函数定义:void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLflo ...
随机推荐
- 剑指offer--33.丑数
本来用数组做标志位,但是测试数据有第1500个,859963392,惹不起哦 ------------------------------------------------------------- ...
- poj1655(dfs,树形dp,树的重心)
这是找树的重心的经典题目. 树的重心有下面几条常见性质: 定义1:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心.定义2:以这个点为根,那么所有的子树(不算整个树自身)的大 ...
- 正则化项L1和L2的区别
https://blog.csdn.net/jinping_shi/article/details/52433975 https://blog.csdn.net/zouxy09/article/det ...
- svn: E220001: 遇到不可读的路径;拒绝访问。
在客户端试图 svn merge 总是报svn: E220001: 遇到不可读的路径:拒绝访问.这个错误 提示 : SVN 遇到不可读的路径:拒绝访问. 英文是: Unreadable path en ...
- (效果一)js实现上拉加载
实现思路:获取滚动元素的高度,滚动条距离顶部的距离,滚动条的高度, 算式:可视窗口的高度 + 滚动条距离顶部的距离 == 滚动条的高度就说明到底部. HTML <!doctype html> ...
- 【解题报告】[动态规划]RQNOJ - PID72 / 拔河比赛
原题地址:http://www.rqnoj.cn/problem/72 解题思路:基本的01背包问题. 要求的就是在这些人中选出一些人,使得这些人的体重的和 不超过所有人的体重的一半 并最大. 代码: ...
- fn project 试用之后的几个问题
今天试用fnproject 之后自己有些思考,后面继续解决 1. 目前测试是强依赖 dockerhub 的,实际可能不是很方便 2. 如何与k8s .mesos.docker swarm 集成 ...
- 泛型List<T>排序(利用反射)
在最近一个项目中,有需求要对页面中所有的gridview添加排序功能.由于gridview的数据源绑定的是一个集合类List,而不是DataTable,所以无法使用DataView排序功能.另外,不同 ...
- Raid 技术简介
独立硬盘冗余阵列(RAID, Redundant Array of Independent Disks),旧称廉价磁盘冗余阵列,简称硬盘阵列.其基本思想就是把多个相对便宜的硬盘组合起来,成为一个硬盘阵 ...
- (装)Android杂谈--禁止TimePicker控件通过keyboard输入
Android 4.1版本以上用的是类似与ios的滚动时间控件,但是4.1以下,用的TimePicker确实通过点击上下按钮来更改时间的,虽然也提供了编辑框编辑,但是可能会超出编辑范围 如果要禁止编辑 ...