Metal中两种projection matrix的推导

接触Metal有一段时间了,但是官方文档中对一个点如何从空间坐标转化成NDC(即 normalized device coordinates)没有作详细的说明。虽然其中原理都和OpenGL、Direct3D大同小异,但是我们知道Metal中NDC和OpenGL还不太一样,而且苹果还少有提及这个,我只在2016年wwdc上看到过这一闪而过的介绍。。
所以,Metal's NDC 究竟是什么样子的。它是的x,y范围都是是[-1, 1],这和OpenGL一样,并且指向上和右。但是z轴范围是[0, 1],并且0在前面,1在后面(从摄象机的视角出发)。
由于NDC的不同,所以MVP变换中的Projection和我们熟悉的OpenGL中的就不一样了。
OpenGL中,透视变换和正交变换是这个样子的。

OpenGL中透视变换矩阵(图片来源:OpenGL Superbible 7th Edition)

OpenGL中正交变换矩阵(图片来源:OpenGL Superbible 7th Edition)

正交变换

正交变换很好理解,就是把一个任意大小的矩形体(可以这么叫吧。。)变换成一个标准的、边长为2的、中心在原点的矩形体。可以把这个矩阵分解成两个矩阵相乘,左边是缩放矩阵,右边是变换矩阵(即平移)。简单的说,就是先把矩形体中心移动到坐标原点,在对其进行缩放。
因此,Metal中的正交变换矩阵也很容易就推导出来了,基本和OpenGL版的一样,就是对z轴的缩放和平移有点区别。

(
2.0 / (right - left),  0.0,                  0.0,                 (left + right) / (left - right),
0.0,                   2.0 / (top - bottom), 0.0,                 (top + bottom) / (bottom - top),
0.0,                   0.0,                  1.0 / (farZ - nearZ), -nearZ / (farZ - nearZ),
0.0,                   0.0,                  0.0,                  1.0
)

矩阵的样子长这样
简单点写可以写成和官方代码中的一样。

var m = matrix_float4x4()
    
m.columns.0.x = 2.0 / width
    
m.columns.1.y = 2.0 / height
    
m.columns.2.z = 1.0 / (zFar-zNear)
    
m.columns.3.z = -zNear / (zFar-zNear)
m.columns.3.w = 1.0
    
return m

透视变换

而透视变换矩阵就稍微复杂一点了。
原理就不在这多说明了,直观上很简单,http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/中有两幅很直观的图表达这个变换的过程。
所以,对于已经设定好的平头椎体区域(frustum),从平头椎体坐标变换成变换后的矩形体坐标应遵循下图公式

平头椎体区域坐标到矩形体坐标(图片来源:Mathematics for 3D Game Programming and Computer Graphics3rd)

原理很简单,就是相似三角形
原理的直观表达(图片来源:CRCFundamentals of Computer Graphics 4th Edition 2015)

而从任意大小的矩形体变换成标准视觉空间(View Volume)上面有讲过,于是就有了这样一堆公式


NDCx轴坐标
NDCy轴坐标

然后将上上上上幅图中公式带入,则有


现在有了x轴、y轴的。而对于z轴,这里又有点小情况。

注意在标准化设备坐标系中OpenGL实际上使用的是左手坐标系(投影矩阵交换了左右手)

所以要翻转z轴,-n对应-1, -f对应1。至于原因我也不太清楚为什么又是左手又是右手的,我猜大概是为了方便接下来的计算。
从x轴y轴的表达式中可以看出都含有一个分母为Pz,于是我们也尝试从z轴弄出同样形式,至于原因,是为了凑成P′= (−x′Pz,−y′Pz,−z′Pz,−Pz)表达P = (x′, y′, z′)。

于是就设方程

代入n、f

解得

于是

所以就可以得出透视矩阵

(以上图片均来自:Mathematics for 3D Game Programming and Computer Graphics 3rd)

这是OpenGL中的过程。

而对于Metal,由于用的是左手坐标系,所以n,f都在坐标正轴,即


换句话说,就是m.columns.2.w = 1
然后就是类似的推导,x、y轴一样,z轴上稍微做一点小改变,由于不需要翻转,但是需要一样的形式(即Pz出现在分母中),所以可列相同的方程解A、B

(
2n / (r - l), 0, (r+l)/r-l, 0,
0, 2n / (t - b), (t+b)/(t-b), 0,
0, 0, farZ / (farZ - nearZ), - nearZ  * farZ / (farZ - nearZ),
0, 0, 1, 0
)

对于只需要fov和aspectRatio的情况,为

    var m : matrix_float4x4 = matrix_float4x4()
    
    let f : Float = 1.0 / tan(FieldOfView / 2.0)
    
    m.columns.0.x = f / aspectRatio
    m.columns.1.y = f
    
    m.columns.2.z = zFar / (zFar - zNear)
    m.columns.2.w = 1.0
    
    m.columns.3.z = -(zNear*zFar)/(zFar-zNear)
    
    return m
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容