现代计算机图形管线渲染图像的方法是处理这两个问题:

1 3D世界的几何图元如何投影成2D图元,进而对应到屏幕的哪些像素

2 根据已有的信息(光照,法向量,贴图),每个像素点应该怎样设置颜色

根据这两个问题,我们有了顶点着色器和片段着色器。

本次研究的内容,是第2个问题中的一个问题。这个问题出现在我们有了贴图,我们有了uv,我们有了片段的位置(并非是像素位置,而是有一定精度的浮点位置),如何根据这部分信息选择颜色。

一切技术都起始于对现有不完美部分的改造,MipMap的概念就是这么来的。任何人从事计算机图形学,必然会遇到这个问题,如果不学习MipMap,不学习三线性过滤,也必然会想出一个类似的解决办法,因此,这两个东西是技术发展的必然,是自然而然的出现,而并非是为了技术而技术的Geek玩意。

首先,根据当前片段的位置和相邻3个顶点的uv值(认为是三角形),我们可以计算出该片段所在位置的插值uv。根据这个uv,映射到贴图的像素坐标空间,必然得到一个带浮点的小数二维坐标。想当然的,我们认为离这个坐标最近的像素颜色,就是这个片段的颜色。这样,我们就有了点采样。

然而这样的效果并不完美,因为凡是计算出来的二维坐标在该像素+-0.5范围内的一切片段,都会使用这同一个颜色,当三角形被放大(也就是摄像机比较近或摄像机fov比较小),屏幕上会有多个像素点取到同一个贴图颜色,产生销魂的马赛克效果,这便是ps主机和许多老游戏机(任天堂直到nds)全部都有的问题。它们只能使用点采样。

这显然太粗糙了,于是聪明人想了一个办法,将计算出来的浮点贴图坐标空间的位置,取周围4个像素,并按照距离的加权计算一个混合颜色(这就是传说中不明觉厉的图像卷积)。于是,图像没那么粗糙了,过渡变得更加平滑,这就叫做线性采样。

看起来已经没有什么可以优化的了,毕竟贴图分辨率在那摆着。然而,线性过滤在三角形较小的时候会展现的不完美。当三角形较小时(也就是贴图被缩小了),这种方式计算出来的颜色会跳动,因为贴图较大,信息过大,同时大量信息被压缩在相对比较小的空间中,则像素变化微小时,色彩变化会剧烈,参考示波器,如果扩大坐标轴的时间范围,波就会变得密集,从而在绝对的屏幕距离内变化会更加剧烈。这样就会产生下面的效果,在远处的图像事实上已经看不到任何有用信息,被剧烈的过渡掩盖了:

这点上,低像素图像有优势。因为像素低,信息量没有那么大,在有限空间的过渡就不会那么剧烈(事实上可以把一个低分辨率的图像放大,在参考大分辨率的同类图像,在任何方向上,低分辨率图放大以后的色彩变化都要更加柔和)。

于是聪明人又想出来一个办法,保存同一个图像的不同分辨率版本,当三角形在屏幕上的大小相对于图像远远要小,则使用低分辨率版本,具体使用多低的分辨率,取决于三角形在屏幕上映射的尺寸和它所用到的uv范围。由于计算机处理2倍关系时速度更快,一般使用成两倍关系的图像,于是,必须规定图像的长和宽是2的幂。

这就是MipMap的由来,它在远距离能达到如下效果,完美解决色彩的剧烈震荡:

MipMap,双线性都有了,这个画面静态的看,也没有太多可以挑剔的。

然而,当摄像机运动,同一个三角形越来越大或越来越小的做渐变缩放时,在MipMap切换不同分辨率图像的临点处由于切换了图像,会有非常明显的变化:

上面标红的地方,当摄像机往前移动,它会突然变清晰,这个过程很明显,看起来很违和。

于是,我们有了最后的三线性过滤:

计算出来选择MipMap的凭据,必然是一个浮点数(不可能那么凑巧是一个整数,即便是整数,也能看成小数很小的浮点数),那么我们对前一个MipMap和后一个分辨率的MipMap都进行双线性插值,然后根据这个MipMap凭据,再将两个插值结果进行一个插值,得到一个中间数。

这样,就解决了动态情况下突变的问题,摄像机接近的时候,它是慢慢的变清晰的。

综上所述:

点采样,马赛克

线性采样,远距离麻麻点点

MipMap的线性采样和三线性静态图是没有区别的,区别在于动起来,三线性能够渐变。

MipMap与三线性过滤的更多相关文章

  1. 深入学习jQuery选择器系列第三篇——过滤选择器之索引选择器

    × 目录 [1]通用形式 [2]首尾索引 [3]奇偶索引[4]范围索引 前面的话 上一篇介绍了过滤选择器中的子元素选择器部分,本文开始介绍极易与之混淆的索引选择器 通用形式 $(':eq(index) ...

  2. Liunx运维(三)-文件过滤及内容编辑处理

    文档目录: 一.cat:合并文件或查看文件内容 二.tac:反向显示文件内容 三.more:分页显示文件内容 四.less:分页显示文件内容 五.head:显示文件头部内容 六.tail:显示文件尾部 ...

  3. Python 三种过滤去重方法

    SET集合去重 set(1,1,2) REDIS去重 布隆过滤器

  4. SVM(三)线性支持向量机

    本文是在微信公众号发表的原创~ 额,图片粘不过来~就把链接给你们吧 http://mp.weixin.qq.com/s?__biz=MjM5MzM5NDAzMg==&mid=400740076 ...

  5. 【转】MipMap

    原文地址http://www.cppblog.com/wc250en007/archive/2011/08/06/152653.html 首先从MIPMAP的原理说起,它是把一张贴图按照2的倍数进行缩 ...

  6. MipMap

    MipMap 首先从MIPMAP的原理说起,它是把一张贴图按照2的倍数进行缩小.直到1X1.把缩小的图都存储起来.在渲染时,根据一个像素离眼睛为之的距离,来判断从一个合适的图层中取出texel颜色赋值 ...

  7. opengl的mipmap

    压缩纹理是不能调用glGenerateMipmap生成mipmap的. DDS和PVR都不行. 强行调用会产生GL_INVALID_OPERATION的错误. PNG格式试验了glGenerateMi ...

  8. 纹理过滤模式中的Bilinear、Trilinear以及Anistropic Filtering

    1. 为什么在纹理采样时需要texture filter(纹理过滤). 我们的纹理是要贴到三维图形表面的,而三维图形上的pixel中心和纹理上的texel中心并不一至(pixel不一定对应textur ...

  9. OpenGL ES学习笔记(三)——纹理

    首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <OpenGL ES学习笔记( ...

随机推荐

  1. c#中ref和out 关键字

    问题:为什么c#中要有ref和out?(而java中没有)需求假设:现需要通过一个叫Swap的方法交换a,b两个变量的值.交换前a=1,b=2,断言:交换后a=2,b=1. 现编码如下: class ...

  2. Java学习——开端

    学号 <Java程序设计>第1周学习总结(1) 教材学习内容总结(第一章) Java最早是由Sun公司研发,原称Oak(橡树),开发者之一的James Gosling被尊称为Java之父. ...

  3. git 学习笔记3--status flow

    1.status 通过执行 git status 命令,查看输出的信息来理解文件所处的状态以及可能的动作. 1.1 nothing to commit (working directory clean ...

  4. js jQuery笔记

    jQuery 1.几种获取子元素的方法及区别 children方法获得的仅仅是元素一下级的子元素,即:immediate children. find方法获得所有下级元素,即:descendants ...

  5. git的合并与推送

    集中式合作模式 1.git fetch 获取远程更新 2.git merge origin/master 进行合并,如果报错,则相应解决.注:你得用git bash命令行执行才能看见报错详情,用ecl ...

  6. 编程思想┊从实例谈面向对象编程(OOP)、工厂模式和重构

    有了翅膀才能飞,欠缺灵活的代码就象冻坏了翅膀的鸟儿.不能飞翔,就少了几许灵动的气韵.我们需要给代码带去温暖的阳光,让僵冷的翅膀重新飞起来.结合实例,通过应用OOP.设计模式和重构,你会看到代码是怎样一 ...

  7. 【BZOJ3631】松树的新家 树链剖分

    BZOJ3631 松树的新家 Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  8. Spring In Action(第三版)读书笔记

    第一章 Spring之旅 POJO: plain old java object 简单的java对象 DI:Dependency Injection 依赖注入 构造器注入:构造时作为构造器参数传入 p ...

  9. Linux进程含义知多少

    理想情况下,您应该明白在您的系统中运行的每一个进程.要获得所有进程的列表,可以执行命令 ps -ef(POSIX 风格)或 ps ax(BSD 风格).进程名有方括号的是内核级的进程,执行辅助功能(比 ...

  10. IOS启动顺序

    一.UIApplicationMain的执行步骤1.创建一个UIApplication对象,一个程序对应一个UIApplication对象(单例),UIApplication对象是程序的象征2.接下来 ...