iOS SceneKit 啥是 inversedTransform? (对于假人)
Posted
技术标签:
【中文标题】iOS SceneKit 啥是 inversedTransform? (对于假人)【英文标题】:iOS SceneKit what is inversedTransform? (for dummies)iOS SceneKit 什么是 inversedTransform? (对于假人) 【发布时间】:2021-06-03 17:46:10 【问题描述】:我是 Metal
和 SceneKit
的 3D 渲染新手。我看到需要将特定的“逆”变换传递给渲染器/着色器。我打印了变换,看不到它们之间的关系。谷歌搜索结果是一堆相当高级的主题。
所以我问一个像我这样的傻瓜的问题:
着色器的“反向”视图变换是什么意思?
如果我不反转变换会发生什么?
// Apple code below (with original comment):
// Pass view-appropriate image transform to the shader modifier so
// that the mapped video lines up correctly with the background video.
let sceneView = renderer as? ARSCNView,
let frame = sceneView.session.currentFrame
let affineTransform = frame.displayTransform(for: .portrait, viewportSize: self.view.bounds.size)
let transform = SCNMatrix4(affineTransform)
let inverse = SCNMatrix4Invert(transform) // pass to shader
transform:
SCNMatrix4(
m11: 0.0, m12: 1.0, m13: 0.0, m14: 0.0,
m21: -1.5227804, m22: 0.0, m23: 0.0, m24: 0.0,
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
m41: 1.2613902, m42: -0.0, m43: 0.0, m44: 1.0)
----
inversed:
SCNMatrix4(
m11: 0.0, m12: -0.6566935, m13: 0.0, m14: 0.0,
m21: 1.0, m22: 0.0, m23: 0.0, m24: 0.0,
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
m41: 0.0, m42: 0.8283468, m43: 0.0, m44: 1.0)
这里有一些信息表明上述矩阵是平移、旋转和缩放的组合。虽然 CGAffine 变换将它们拆分为不同的元素,但在这里它们都被夹在一起:
https://www.javatpoint.com/computer-graphics-3d-inverse-transformations
【问题讨论】:
我的数学演讲不太好,但基本上,变换是一个矩阵,可以让你从一个坐标系转到另一个坐标系。它通过改变一个向量来做到这一点,你正在从一组基向量转换为另一组基向量。而逆变换则相反。如果您有一个变换,可以让您从世界坐标系转到视图坐标系(以便在乘以任何世界向量后成为视图向量),则反向执行相反的操作:将视图向量返回到世界向量。矩阵和变换在 3D 中是相同的,因为所有线性变换都只能表示为矩阵。 基本上,这归结为线性代数和仿射变换。有文章和书籍可以更好地解释它,尽管我没有具体的链接。 【参考方案1】:我发现了对对象坐标在传递到渲染器之前所经过的步骤的出色描述:
-
在渲染相机图像时,逆变换使用相机内在函数将相机 X、Y + 可选深度转换为对象空间。相机内在函数将 3D 转换为 2D,因此逆变换从 2D 变为 3D
const auto localPoint = cameraIntrinsicsInversed * simd_float3(cameraPoint, 1) * depth;
-
对象(本地)空间到世界空间(苹果示例中的 localToWorld 矩阵)(3x3 矩阵)
世界空间到视图/眼睛/相机空间 viewMatrix(3x3 矩阵,Z 轴指向观察者/相机,Y 轴向上)
使用查看投影矩阵(4x4 矩阵,具有 W 分量)查看空间到剪辑空间。 大于 W 的 X、Y、Z 将被剪裁或剔除 - 不渲染。使用
matrix_float4x4_perspective
函数创建
我们现在有一个矩阵序列,可以将我们从 对象空间到剪辑空间,这是 Metal 期望的空间 由我们的顶点着色器返回的顶点。乘以所有 这些矩阵一起产生一个模型视图投影(MVP)矩阵, 这就是我们将实际传递给顶点着色器的内容,以便每个 顶点可以在 GPU 上乘以它。
// pseudocode, missing some matrix padding for multiplication purposes:
modelViewProjection = vertXYZ * localToWorld * viewMatrix * projectionMatrix
渲染器执行进一步的转换:
-
剪辑空间到 NDC(标准化设备坐标)(半立方体 x,y -1 到 1,z 0 到 1)
NDC 到窗口像素位置
【讨论】:
【参考方案2】:当相机捕获 SCNScene 时,场景深度数据会丢失 - 这是因为 3D 对象被映射到 2D 图像平面上。但是,如果我们想要进行反向变换,那么它对于仅考虑 2D 图像来重建 3D 场景是行不通的。我们还需要深度。这就是inversedTransform
的用途。
【讨论】:
以上是关于iOS SceneKit 啥是 inversedTransform? (对于假人)的主要内容,如果未能解决你的问题,请参考以下文章
在 SCNSphere 上获取点击位置 - Swift (SceneKit) / iOS