.net是建网站的吗,seo软件排行榜前十名,中国建设银行舟山分行网站,网络游戏推广在上一章中#xff0c;您通过在 vertex 函数中计算position#xff0c;来平移顶点和在屏幕上移动对象。但是#xff0c;在 3D 空间中#xff0c;您还想执行更多操作#xff0c;例如旋转和缩放对象。您还需要一个场景内摄像机#xff0c;以便您可以在场景中移动。
要移动…
在上一章中您通过在 vertex 函数中计算position来平移顶点和在屏幕上移动对象。但是在 3D 空间中您还想执行更多操作例如旋转和缩放对象。您还需要一个场景内摄像机以便您可以在场景中移动。
要移动、缩放和旋转三角形您将使用矩阵 - 一旦您掌握了一个三角形就可以一次旋转具有数千个三角形的模型
对于我们这些不是数学天才的人来说向量和矩阵可能有点可怕。幸运的是在使用数学时您不必总是需要知道引擎盖下的内容。为了提供帮助本章的重点不是数学而是矩阵。在学习本章的过程中您将逐渐扩展您的线性代数知识因为您将了解矩阵可以为您做什么以及如何操作它们。
变换
查看下面的图片 使用矢量图像编辑器 Affinity Designer您可以通过一系列仿射变换来缩放和旋转猫。Affinity Designer 不会单独计算每个位置而是创建一个包含变换组合的变换矩阵。然后它将变换应用于每个元素。
注 仿射表示完成变换后所有平行线都保持平行。
当然没有人愿意移动、缩放和旋转猫因为它们可能会咬人。因此您将平移、缩放和旋转三角形。
开始项目和设置
➤ 打开并运行位于本章 starter 文件夹中的 starter 项目。 此项目渲染一个三角形两次而不是渲染一个四边形。 在 Renderer 的 drawin 中您将看到两个 draw 调用每个三角形一个。渲染器将 position 传递给 vertex 函数将 color 传递给 fragment 函数它对每个三角形执行此操作。灰色三角形位于其原始位置红色三角形应用变换。
➤ 在继续下一步之前请确保您理解 Renderer 的 drawin 中的代码和 Shaders.metal 中的 vertex 函数。
ContentView.swift 现在位于 SwiftUI 视图组中它在Metal View上显示网格以便您可以更轻松地可视化顶点位置。
平移
starter项目展示两个三角形 • 没有任何变换的灰色三角形。 • 使用position simd_float30.3 -0.4 0 平移的红色三角形。 在上一章的第一个挑战中您计算了着色器函数中每个顶点的位置。更常见的计算机图形范例是在顶点缓冲区中设置模型每个顶点的位置通常从文件加载然后将矩阵发送到顶点着色器着色器包含模型当前位置、旋转和缩放。
顶点和矩阵
您可以更好地将position描述为位移矢量[0.3 -0.4 0]。每个顶点从 x 方向上移动 0.3 个单位在 y 方向上移动 -0.4 个单位。
在下图中蓝色箭头是矢量。 左侧蓝色箭头是值为 [-1 2] 的向量。右侧的蓝色箭头靠近 cat 的箭头也是值为 [-1 2] 的向量。positionpoint是空间中的位置而向量是空间中的位移。换句话说向量包含移动的数量和方向。如果你要用蓝色向量来移动猫它最终会到达点 2 4。这是猫的位置 3 2 加上向量 [-1 2]。
此 2D 向量是一个 1x2 矩阵。它有一列和两行。
注 您可以按行或列对矩阵进行排序。simd 库按列优先顺序构造矩阵这意味着列在内存中是连续的。simd_double2x4 是包含两列四行的矩阵。
矩阵是二维数组。即使是单个数字 1 也是一个 1×1 矩阵。实际上数字1是独一无二的因为用任何数字乘以1都是它本身。所有方阵行数和列数相等的矩阵都有一个矩阵具有和1的概念相等的矩阵——单位矩阵。任何向量或矩阵乘以单位矩阵都是它本身。
4×4 单位矩阵如下所示全是 0对角线 1 除外 3D 变换矩阵有 4 行和 4 列。变换矩阵左上角的 3×3 矩阵中包含缩放和旋转信息平移信息在最后一列中。将向量和矩阵相乘时左侧矩阵或向量的列数必须等于右侧的行数。例如您不能将 float3 乘以 float4×4。
矩阵的魔力
当您将矩阵相乘时您将它们合并为一个矩阵。然后您可以将向量乘以此矩阵来变换向量。例如您可以设置旋转矩阵和平移矩阵。然后您可以使用以下代码计算转换后的位置 translationMatrix * rotationMatrix * positionVector
矩阵乘法从右向左进行。在这里旋转应用于平移之前的位置。 这是线性代数的基础——如果你想继续学习计算机图形学你需要更全面地理解线性代数。目前了解设置转换矩阵的概念可以让你走很长的路。
创建矩阵
➤ 打开 Renderer.swift找到你在 drawin 中渲染第一个灰色三角形的位置。 ➤ 将position代码从
var position simd_float3(0, 0, 0)
renderEncoder.setVertexBytes(position,length: MemoryLayoutSIMD3Float.stride,index: 11)
改为
var translation matrix_float4x4()
translation.columns.0 [1, 0, 0, 0]
translation.columns.1 [0, 1, 0, 0]
translation.columns.2 [0, 0, 1, 0]
translation.columns.3 [0, 0, 0, 1]
var matrix translation
renderEncoder.setVertexBytes(matrix,length: MemoryLayoutmatrix_float4x4.stride,index: 11)
在这里您将创建一个单位矩阵和一个要发送到 GPU 的渲染命令。
➤ 找到第二个红色三角形的position代码并更改
position simd_float3(0.3, -0.4, 0)
renderEncoder.setVertexBytes(position,length: MemoryLayoutSIMD3Float.stride,index: 11)
为
let position simd_float3(0.3, -0.4, 0)
translation.columns.3.x position.x
translation.columns.3.y position.y
translation.columns.3.z position.z
matrix translation
renderEncoder.setVertexBytes(matrix,length: MemoryLayoutmatrix_float4x4.stride,index: 11)
您将使用此矩阵来平移顶点着色器中的position。
➤ 打开 Shaders.metal然后更改
constant float3 position [[buffer(11)]])
为 constant float4x4 matrix [[buffer(11)]])
您将接收传入着色器中的矩阵。
➤ 在 vertex 函数中更改 float3 translation in.position.xyz position;
为
float3 translation in.position.xyz matrix.columns[3].xyz;
使用矩阵的第四列作为位移向量。
➤ 构建并运行。到目前为止输出是相同的。 请记住此矩阵还将保存旋转和缩放信息。要计算position您需要执行矩阵乘法而不是添加平移位移向量。 ➤ 将 vertex 函数的内容改为
float4 translation matrix * in.position;
VertexOut out {.position translation
};
return out;
➤ 构建并运行应用程序您会发现仍然没有变化。 现在您可以在 Renderer 中向矩阵添加缩放和旋转而无需每次更改着色器函数。
缩放
➤ 打开 Renderer.swift然后在 drawin 中找到第二个红色三角形中设置 matrix 的位置。 ➤ 在 matrix translation 之前添加以下内容
let scaleX: Float 1.2
let scaleY: Float 0.5
let scaleMatrix float4x4([scaleX, 0, 0, 0],[0, scaleY, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1])
您可以像这样初始化一个矩阵将列定义为数组而不是像在“平移”中所做的那样分配给列。scaleMatrix.columns.0 现在包含 [1.2 0 0 0]。
无需过多地进行数学研究就可以使用此代码来设置缩放矩阵。 ➤ 将 matrix translation更改为 matrix scaleMatrix
将平移矩阵乘以缩放矩阵而不是乘以平移矩阵。
➤ 构建并运行应用程序。 在 vertex 函数中矩阵将三角形的每个顶点乘以 x 和 y 缩放因子。 ➤ 将 matrix scaleMatrix 更改为 matrix translation * scaleMatrix
此代码平移缩放的三角形。
➤ 构建并运行应用程序。 旋转
执行旋转的方式与缩放类似。 ➤ 将 matrix translation * scaleMatrix改为
let angle Float.pi / 2.0
let rotationMatrix float4x4([cos(angle), -sin(angle), 0, 0],[sin(angle), cos(angle), 0, 0],[0, 0, 1, 0],[0, 0, 0, 1])
matrix rotationMatrix
在这里您可以设置围绕 z 轴旋转的角度以弧度为单位。
注意Float.pi / 2.0 与 90° 相同均为 1.5708 弧度。弧度是计算机图形学中的标准单位。这是将度数转换为弧度的公式度数 * pi / 180 弧度。
➤ 构建并运行您将看到红色三角形的每个顶点如何围绕原点 [0 0 0] 旋转 90°。 ➤ 将 matrix rotationMatrix 替换为
matrix translation * rotationMatrix * scaleMatrix
此代码首先缩放每个顶点然后旋转然后平移。
➤ 构建并运行。 矩阵运算的顺序很重要。尝试更改顺序看看会发生什么。 缩放和旋转发生在原点 坐标 [0 0 0]。但是有时您可能希望围绕不同的点进行旋转。例如当三角形处于其原始位置即与灰色三角形相同的位置和旋转角度时让我们围绕三角形的最右边点旋转三角形。 要旋转三角形您需要设置一个平移矩阵其中向量位于原点和最右侧点之间执行以下步骤 1. 使用平移矩阵平移所有顶点。
2. 旋转。
3. 再次平移回来。
➤ 在对红色小三角设置矩阵之前添加以下代码
translation.columns.3.x triangle.vertices[2].x
translation.columns.3.y triangle.vertices[2].y
translation.columns.3.z triangle.vertices[2].z
将变换矩阵设置为从原点移动到灰色三角形的第三个顶点即最右侧的点。 记住这些步骤。第 1 步是按距原点的距离平移所有顶点。您可以通过将矩阵设置为顶点的向量值并使用平移矩阵的逆矩阵来实现此目的。
在执行以下每个步骤后不要忘记构建并运行应用程序以便您可以查看矩阵乘法的作用。 ➤ 将matrix translation * rotationMatrix * scaleMatrix 更改为 matrix translation.inverse
此代码将最右侧的顶点放在原点处以相同的距离平移所有其他顶点。 ➤ 将您刚刚输入的代码更改为
matrix rotationMatrix * translation.inverse 三角形绕原点旋转 90°。 ➤ 将您刚刚输入的代码更改为 matrix translation * rotationMatrix * translation.inverse
匪夷所思您正在执行按最右侧顶点与原点的距离平移每个顶点的所有步骤。之后您将旋转每个顶点并再次将其平移回来使三角形围绕其最右侧的点旋转。 参考
https://zhuanlan.zhihu.com/p/387152681