Introduction To Perspective Projection

本文介绍了透视投影的基本概念,包括线性插值、OpenGL管线中的归一化设备坐标(NDC)、OpenGL Frustum和Depth Interpolation。文章以一个物理问题引入线性插值,并探讨了在OpenGL中如何将3D图形转换为2D图像,以及如何处理z分量以解决图元遮挡问题。此外,还讨论了glFrustum和gluPerspective函数在定义视景体中的应用,以及如何通过调整z分量确保深度插值的线性关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Introduction To Perspective Projection

丁欧南

Keyword: [Linear Interpolation][Projection Matrix][GL_PROJECTION][GL_PERSPECTIVE_CORRECTION_HINT]

此篇文章介绍Perspective Projection(透视投影).我是一名高一的学生,还未系统学过解析几何,线性代数等知识,错误难免,用语未必规范,这篇文章只是我自学的一些感悟及笔记,写给和我一样的初学者,如有高手指点,本人深表荣幸.如需转载,请注明作者.

 

1.Whetting Your Appetite

先是一道初中时的物理题,为后面的解说做一个铺垫,介绍的是Linear Interpolation(线性插值)的概念:

已知有一破温度计(何以谓破?刻度之间间距虽平均,但间距或大于或小于标准值,谓之破),当其插入0 0C 水里时显示为5 0C ,当其插入100 0C 的沸水中时显示为90 0C ,:当实际水温为50 0C 时此破温度计显示的值是多少?

:因刻度均匀,所以刻度之间的比例与好温度计相同,由此:设显示的数为T,

(90-T)/(T-5)=(100-50)/(50-0) 解出T=47.5 0C .

(为了后续介绍,这里再给一个解法:t为上文所说的比例系数

T=5t+90(1-t)

50=0t+100(1-t)

联立求解,T=47.5 0C )

 

结论:由一个数域(如题目中的好温度计两个端点[0,100])映射到另一个数域(如题目中的破温度计的两个端点[5,90]),如果两个数域都是线性(就如题目中暗示的刻度平均),那么它们对应点成比例(比如5047.5这一对端点).

这道题的应用是把一组坐标映射到另一个范围,这将在介绍NDC(Normalized Device Coordinate,归一化的设备坐标)时用到.

 

2.OpenGL Pipeline

这一节简要介绍OpenGL Pipeline,重点放在Pipeline::Vertex ProcessPipeline::Fragment Process的两个过程:转换到NDC(Normalized Device Coordinate,归一化的设备坐标)和扫描线的插值.

2.1 NDC

NDC既是将视景体内的坐标转换到一个立方体内,x,y,z,w[-1,1].事实上,Projection的目的就是将3D图形转换为PC屏幕可以直接显示的2D图像,所以仅仅通过相似三角形的方法得到x,y分量的值就已足够.但何以需要z,w分量的值?

需要z分量是出于Visibility Determination的需要,直接一点,就是通过z分量(可视为深度值)来决断图元之间的遮挡关系.

由上可见,z分量并非直接参加绘图,它只要保持图元之间的远近关系即可,因此对它的处理可以不像x,y分量那样必须做到线性,所以映射到[-1,1]内的z坐标可以出于某些原因而不呈现线性关系,这个原因将在Depth Interpolation一节中介绍,目前你只要记住NDCz分量的一条准则:z1<z2,则存在映像z 1’ z 2’ [-1,1]z 1’ <z 2’ .

再说为什么需要w分量,Projection并不是3D Transfermation,而是一个Affine Transfermation,所以w分量是必须的.

(事实上Affine Space合并了DirectionPosition,w分量在一个Frame里就是那个Position前的系数)

2.2 Interpolation

我们注意到在用OpenGL Fixed Pipeline绘图时指定颜色的语义都是顶点颜色,那光栅过程(Rasterization)何以知道顶点之间的颜色渐变?,便是插值(Interpolation)的作用了.

就如同破温度计那道题一样,给出两个端点值,且又知两个端点之间呈现线性关系,我们可运用比例计算其间任意点的颜色值.

Diffuse=D1t+D2(1-t) (t为比例系数)

就是为了能够在光栅过程如此方便,线性关系至关重要. Depth Interpolation一节将要介绍使其达到线性关系的方法.

 

3.OpenGL Frustum

void glFrustum(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far);

void gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble near,GLdouble far);

以上就是OpenGL中用来指定视景体(Frustum)的两个方法.功能相同,gluPerspective要求视景体必须对称.

fovy是视野的水平张角,aspect是宽高比

4.Depth Interpolation

由上图左可以看到当扫描线以相同步进扫过近剪裁面时,在图元上却并非相同步进,由此可见其并非线性,因此也就用不到2.2节提到的线性插值.为此,我们需要在转换到NDC时对原图元的z分量动一些手脚,使其写入Depth BufferNDC数据呈现线性关系,并最终使线性插值在光栅阶段可用.现在,我们的目标就是找出经过怎样的变换可以使z呈线性关系.

假定扫描线都是水平的(y分量可以略去).则如上图右.设通过点(x1,z1),(x2,z2)的直线Z=aX+b

由相似三角形的关系,

代入到Z=aX+b,同时解出P:

因为我们期望对P能实现线性插值,因此P3=tP1+(1-t)P2,用上式并代入角标:

化简得:

这样很明显了,我们可以在Depth Buffer中写入关于1/Z线性相关的数值,这样我们就可以在光栅过程中放心使用线性插值了.

另外,由于Perspective Projection转换坐标到左手系,于是Z也就相应>0,1/Z(0,+)上是单调减函数,因此满足2.1节提出的准则,glDepthFunc使用GL_LEQUAL调用.

 

5.Vertex Attribute Interpolation

有时顶点还携带一些信息,像光照,纹理坐标等,我们也希望它们能够让光栅器使用线性插值.

设顶点信息为b,则利用类似温度计那道题的比例式,:

再代入第三节得出的结论:

整理:

最终:

6.Perspective Projection

l,r,b,t,n,f分别对应于glFrustum的参数意义:left,right,bottom,top,near,far

(x,y,z,w)为眼空间坐标,(x’,y’,z’,w’)为投影坐标,(Px,Py,Pz,Pw)NDC

对于x,y,使用相似三角形就可以了:

再将其缩放到[-1,1]的范围,这用上了温度计那道题的第一种解法:

   

代入x’,y’:

现在求Pz,4 Depth Interpolation已经指出:为了光栅过程中的线性关系,Pz应与1/Z呈线性关系,Pz=a/z+b

又由于存在映射(-n,-1),(-f,1),所以:

   

由于最后会除以w分量,所以可以把共同项写入w分量:

合并成矩阵:

Reference

Perspective-Correct Interpolation  [Kok-Lim Low]

Mathematics for 3D Game Programming and Computer Graphics 2nd  [ Charles River Media,Eric Lengyel]

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值