透视校正插值 (Perspective-Correct Interpolation)

问题的提出

在使用光栅化的图形学方法中,法线,颜色,纹理坐标这些属性通常是绑定在图元的顶点上的。在3D空间中,这些属性值在图元上应该是线性变化的。但是当3D顶点被透视投影到2D屏幕之后,如果在2D投影面上对属性值进行线性插值,其对应的属性在3D空间中却不是线性变化的。如下图所示:

图中A,B点被投影到a,b;而c是a,b的中点,从视点连接c点形成一条直线和AB相交于C,很显然C点并不是AB的中点(除非AB平行与ab)。假设A点绑定了属性值k=0k=0k=0, B点属性值k=1k=1k=1,那么经过透视投影后,a和b的属性值自然分别是k=0,k=1k=0,k=1k=0,k=1,如果c的属性值通过a,b的属性值线性插值得到,且c是ab的中点,那么c的属性值为k=0.5k=0.5k=0.5。但由于C不是AB的中点,所以C的属性值k不等于0.5。因此如果在2d投影面上对顶点属性按照2d屏幕坐标进行直接的线性插值,得到的属性值是错误的。在本图的情况下,正确的结果是c的属性值应该等于C的属性值(本图中C更靠近A,因此C的属性值应该是小于0.5),这被称为是透视正确(perspective-correct)的,而直接的线性插值结果是透视不正确的。注意我特意强调“直接”的线性插值不正确,因为我们可以通过对属性值的某个函数进行线性插值,然后再将插值结果用另一个函数转换为我们最终想要的透视正确的属性值。为了找到这个函数,我们先研究一下如何对Z值进行插值。
ps: 图片画的有点问题,c点偏下了,导致看上去C更接近B,以后有空换张图

深度值插值

  • z坐标和深度值
    大多数图形系统会默认投影的时候,camera处于3d空间的原点,视线方向指向+z+z+z或−z-z−z轴,camera上方向为+y+y+y,右方向为+x+x+x,这定义了camera坐标系。投影面垂直于视线,和xyxyxy平面平行,并在视点前方距离ddd处,如果视线方向为+z+z+z轴,则z=dz=dz=d;如果视线方向为−z-z−z轴,则是z=−dz=-dz=−d。显然在此坐标系下,z坐标就表示了深度值。
  • 为什么需要z坐标/深度值
    因为需要使用深度测试实现隐藏面消除,因此投影之后需要知道图元在投影面上所有像素的z值。由于只有图形的顶点(如三角形的三个点)具有z坐标,因此需要使用插值的方式从顶点z坐标计算出图元上其他像素的z坐标值。
  • 问题定义
    如下图所示:我们使用一个视线指向+z+z+z轴的camera坐标系,投影面为z=dz=dz=d。在camera空间,被投影的图元:线ABABAB,具有顶点A(X1,Z1)A(X_1,Z_1)A(X1​,Z1​)和B(X2,Z2)B(X_2,Z_2)B(X2​,Z2​)。顶点A,BA, BA,B被投影到z=dz=dz=d的投影面上得到点a,ba,ba,b。在a,ba,ba,b中间有一点ccc,是通过a,ba,ba,b插值得到,插值系数为sss,即 c=a+s∗(b−a)c = a+ s*(b-a)c=a+s∗(b−a)。连接视点和ccc的直线和ABABAB相交于CCC点(Xt,Zt)(X_t,Z_t)(Xt​,Zt​),显然CCC点投影到z=dz=dz=d上得到ccc点。现在已知A,BA,BA,B点的Z坐标Z1,Z2Z_1,Z_2Z1​,Z2​,以及ccc点的插值系数sss,需要找到一个表达式求出CCC点的Z坐标ZtZ_tZt​。

  • 推导z坐标插值关系式 Zt=f(Z1,Z2,s)Z_t = f(Z_1,Z_2,s)Zt​=f(Z1​,Z2​,s)
    首先,定义直线ABABAB为 ax+bz=c(c不等于0)ax+bz=c (c不等于0)ax+bz=c(c不等于0)
    对于ABABAB上任意一点(X,Z)(X,Z)(X,Z)投影到z=dz=dz=d上的点为(u,d)(u,d)(u,d)。根据相似三角形关系有:
    Xu=Zd,即X=Zud\frac{X}{u} = \frac{Z}{d},即 X=\frac{Zu}{d} uX​=dZ​,即X=dZu​
    将Xt=ZtudX_t = \frac{Z_tu}{d}Xt​=dZt​u​代入AB的方程:
    a(Ztud)+bZt=ca(Z_t\frac{u}{d}) + bZ_t = c a(Zt​du​)+bZt​=c
    Zt(aud+b)=cZ_t(a\frac{u}{d} + b) = c Zt​(adu​+b)=c
    1Zt=audc+bc(1)\frac{1}{Z_t} = \frac{au}{dc} + \frac{b}{c} \tag1 Zt​1​=dcau​+cb​(1)
    因为 u=u1+s(u2−u1)=u1(1−s)+u2su = u_1 + s (u_2-u_1) = u_1(1-s)+u_2su=u1​+s(u2​−u1​)=u1​(1−s)+u2​s,代入(1)(1)(1)
    1Zt=au1(1−s)dc+au2sdc+bc=au1dc(1−s)+au2dcs+bc(1−s)+bcs\frac{1}{Z_t} = \frac{au_1(1-s)}{dc} + \frac{au_2s}{dc} + \frac{b}{c} = \frac{au_1}{dc}(1-s) + \frac{au_2}{dc}s + \frac{b}{c}(1-s) + \frac{b}{c}s Zt​1​=dcau1​(1−s)​+dcau2​s​+cb​=dcau1​​(1−s)+dcau2​​s+cb​(1−s)+cb​s
    1Zt=(au1dc+bc)(1−s)+(au2dc+bc)s(2)\frac{1}{Z_t} = (\frac{au_1}{dc} + \frac{b}{c})(1-s) + (\frac{au_2}{dc} + \frac{b}{c})s \tag2 Zt​1​=(dcau1​​+cb​)(1−s)+(dcau2​​+cb​)s(2)
    根据(1)(1)(1) 有
    1Z1=au1dc+bc\frac{1}{Z_1} = \frac{au_1}{dc} + \frac{b}{c} Z1​1​=dcau1​​+cb​
    1Z2=au2dc+bc\frac{1}{Z_2} = \frac{au_2}{dc} + \frac{b}{c} Z2​1​=dcau2​​+cb​
    代入(2)(2)(2)得
    1Zt=1Z1(1−s)+1Z2s(3)\frac{1}{Z_t} = \frac{1}{Z_1}(1-s) + \frac{1}{Z_2}s \tag3 Zt​1​=Z1​1​(1−s)+Z2​1​s(3)
    从(3)(3)(3)可知,在插值计算Z值前先计算顶点Z坐标的倒数,对倒数进行插值,然后将结果再次取倒数就可以在屏幕空间得到正确的视图空间Z值。而在实际的图形系统中,往往不需要再次取倒数得到视图空间的Z值。例如OpenGL中,会把投影后的Z值构建为Z′=AZ+BZ' = \frac{A}{Z} + BZ′=ZA​+B 的形式,且Z’的范围被归一化到[−1,1][-1,1][−1,1]之间,然后再经过depth range映射为[0,1][0,1][0,1]的范围存储到深度缓冲中,0为near plane的Z值,1为far plane的Z值,值越大离视点越远。这样处理后的Z值是和视图空间Z值倒数1Z\frac{1}{Z}Z1​成线性关系,可以直接在光栅化时进行插值。

顶点属性的插值

正如本文一开始说的,直接对顶点属性进行线性插值得到的结果是透视不正确的。为了透视正确,顶点属性需要和z坐标成正比。上图中,A点具有属性I1I_1I1​, B点具有属性I2I_2I2​,我们计算C点的属性ItI_tIt​:
It−I1I2−I1=Zt−Z1Z2−Z1\frac{I_t - I_1}{I_2 - I_1} = \frac{Z_t - Z_1}{Z_2 - Z_1} I2​−I1​It​−I1​​=Z2​−Z1​Zt​−Z1​​
而根据(3)(3)(3):
Zt=11Z1(1−s)+1Z2sZ_t = \frac{1}{\frac{1}{Z_1}(1-s) + \frac{1}{Z_2}s} Zt​=Z1​1​(1−s)+Z2​1​s1​
代入上式,解出ItI_tIt​:
It−I1I2−I1=11Z1(1−s)+1Z2s−Z1Z2−Z1=11+(1−s)Z2sZ1=Z1sZ1s+Z2(1−s)\frac{I_t - I_1}{I_2 - I_1} = \frac{\frac{1}{\frac{1}{Z_1}(1-s) + \frac{1}{Z_2}s} - Z_1}{Z_2 - Z_1} = \frac{1}{1 + \frac{(1-s)Z_2}{sZ_1}} = \frac{Z_1s}{Z_1s+Z_2(1-s) } I2​−I1​It​−I1​​=Z2​−Z1​Z1​1​(1−s)+Z2​1​s1​−Z1​​=1+sZ1​(1−s)Z2​​1​=Z1​s+Z2​(1−s)Z1​s​
It=(I1∗Z2∗(1−s)+I2∗Z1∗s)(Z1∗s+Z2∗(1−s))I_t = \frac{( I1*Z2*(1-s) + I2*Z1*s )}{( Z1*s + Z2*(1-s) )} It​=(Z1∗s+Z2∗(1−s))(I1∗Z2∗(1−s)+I2∗Z1∗s)​
上下同除以Z1Z2Z_1Z_2Z1​Z2​得
It=(1−s)I1Z1+sI2Z2(1−s)1Z1+s1Z2It = \frac{ (1-s)\frac{I_1}{Z_1} + s\frac{I_2}{Z_2} } { (1-s)\frac{1}{Z_1} + s\frac{1}{Z_2} } It=(1−s)Z1​1​+sZ2​1​(1−s)Z1​I1​​+sZ2​I2​​​
从上式可知,在投影面上对属性插值时,先对IZ\frac{I}{Z}ZI​进行插值,然后将结果除以1Z\frac{1}{Z}Z1​插值的结果。这样就得到了属性的透视校正插值。

图形学基础之透视校正插值相关推荐

  1. 【转】图形学基础之透视校正插值

    原文链接:https://blog.csdn.net/n5/article/details/100148540

  2. 【图形学】关于透视校正

    关于透视校正 使用如下的矩阵进行透视投影: p r o j = [ n 0 0 0 0 n 0 0 0 0 n + f n f 0 0 − 1 0 ] \mathrm{proj}=\begin{bma ...

  3. 计算机图形学基础考试题,计算机图形学基础复习题

    <计算机图形学基础复习题>由会员分享,可在线阅读,更多相关<计算机图形学基础复习题(8页珍藏版)>请在人人文库网上搜索. 1.计算机图形学基础复习题 一.判断题 1. PNG( ...

  4. 图形学基础|基于SDF的卡通阴影图

    图形学基础|基于SDF的卡通阴影图 文章目录 图形学基础|基于SDF的卡通阴影图 一.前言 二.SDF(Signed Distance Field) 三.阴影图生成 3.1 SDF生成 3.2 插值 ...

  5. 计算机图形学基础如何学,计算机图形学基础思考

    计算机图形学基础思考 2019-08-07 版权声明 举报文章 第3届太平洋计算机图形学学术会议(PaeifieGraphies'95)于8月21日至24日在韩国汉城召开.会议邀请了专家作讲演,题目为 ...

  6. 图形学基础 | 计算机图形学MOOC学习笔记

    计算机图形学 学习笔记 视频链接 http://www.icourse163.org/learn/CAU-45006?tid=1001746004#/learn/announce 补充一下一些图形学基 ...

  7. 【图形学基础】光栅图

    [图形学基础]光栅图 文章目录 [图形学基础]光栅图 前言 1. 初识光栅图 2. 光栅设备 2.1. 展示型光栅设备 2.2. 硬拷贝型光栅设备 2.3. 输入型光栅设备 3. 图片,像素,几何 3 ...

  8. 计算机图形图像学基础,计算机图形学基础(第2版)

    计算机图形学基础(第2版) 语音 编辑 锁定 讨论 上传视频 <计算机图形学基础(第2版)>是2011年电子工业出版社出版的图书,作者是陆枫.何云峰. 书    名 计算机图形学基础(第2 ...

  9. 【计算机图形学基础】投影矩阵

      最近在重温计算机图形学的基础知识,期望能做到温故知新,加深对其的理解,以便能从容应对工作中各种情况.   小弟水平有限,若有不正确之处,欢迎大家批评指正. 相关文章链接: [计算机图形学基础]线性 ...

最新文章

  1. 3D打印机分类与速度
  2. 【iOS-cocos2d游戏引擎开发之一】搭建cocos2d游戏引擎环境,创建第一个HelloWorld!...
  3. JAVA_OA管理系统(四)番外篇:使用Spring注解注入属性
  4. 云计算,从“资源时代”迈入“功能时代”
  5. python3纵向输出字符串_笔记||Python3之字符串格式化输出
  6. 下载Bootstrap3
  7. 如何做好云计算的运维工作
  8. php提示修改成功,提示修改成功后怎么换回原来的页面
  9. java十六进制与字符串_JAVA十六进制与字符串的转换方法
  10. 基于16QAM调制的OFDM系统仿真实现(MATLAB)
  11. 网易云音乐歌曲带时间轴歌词的提取
  12. php gmssl,centos7 php7 gmssl编译安装
  13. STM32的ucgui移植
  14. love death+robot中的哲学思考
  15. 解决chrome浏览器打不开
  16. 办公大师系列经典丛书 诚聘译者
  17. 有些计算机病毒没有传染性,电脑病毒有没传染性介绍
  18. Error: EBUSY: resource busy or locked
  19. Solidworks异型孔打孔失败原因分析
  20. stm32学习笔记1

热门文章

  1. 抖音C#版,自己抓第三方抖音网站
  2. 常见的存储虚拟化技术(HCIE云方向)
  3. 怎么把备忘录中的视频导到手机相册里
  4. websocket 给服务端发送太长数据处理(The decoded text message was too big for the output buffer and the endpoint )
  5. 简单几步实现RTMP直播
  6. 【云原生 | Kubernetes 系列】K8s 实战 管理 Secret 详解
  7. Python之解决tkinter.PhotoImage不显示图片的问题 Python3
  8. MarkdownPad2注册码——亲测有效
  9. js二维码样式生成插件easy.qrcode.js
  10. 电脑同时开有线和无线,优先使用哪个?