binglu’s blog
← 返回文章
开发实践

一个有点意思的小科普--你的电脑的图像是怎么呈现的

冰露9 分钟

随着科技的发展,我们的生活有了游戏的存在,而你在电脑里看到的任何 3D 物体,无论是游戏里的角色,还是电影里的飞船,其本质都是由无数个微小的三角形“面片”拼接而成的。

第一步:定位 - “三维空间”中的每个点都需要坐标

文章配图

三角形有三个顶点。为了让电脑知道这个顶点在 3D 空间里的确切位置,我们需要给它一组 XYZ 坐标。这就像报出经度、纬度和海拔,确保每个点都能精准地“归位”,这样桌子才不会飞到天花板上。

这简单的一句话背后,其实回答了一个根本性问题:电脑如何理解现实世界中的“空间”和“形状”?

电脑本身不认识“上下左右”,也不理解“桌子”或“人”,它只认识数字。因此,我们必须创造一个它能理解的、完全数学化的“虚拟空间”。

  1. 建立参考系:笛卡尔坐标系 我们引入了你在数学课上非常熟悉的笛卡尔坐标系 (Cartesian Coordinate System),但将其扩展到了三维。

    • 原点 (Origin):首先,我们在无限大的虚拟空间中定义一个绝对的中心点 (0, 0, 0),它是一切测量的起点。
    • 坐标轴 (Axes):我们从原点出发,画出三条相互垂直的“尺子”,也就是 X、Y、Z 轴。它们分别定义了空间中的左右、上下、前后这三个基本维度。
    • 坐标 (Coordinates):现在,空间中任何一个点的位置,都可以用它在这三把“尺子”上的刻度值 (x, y, z) 来唯一确定。比如,(5, 10, -20) 就表示一个点在 X 轴正方向 5 个单位、Y 轴正方向 10 个单位、Z 轴负方向 20 个单位的地方。
  2. 从点到形:顶点、连线与三角形网格 有了坐标系,我们可以描述“点”了。但一个孤立的点没有意义,如何描述“形状”?答案是“连接”。

    • 顶点 (Vertex):我们先在物体的关键“拐角”处标记出一系列的点,并记录下它们的坐标。这些点就是模型的顶点
    • 索引列表 (Index List):光有一堆顶点坐标,电脑看到的是一团“星云”,而不是一个模型。因此,我们还需要一张“连接说明书”,告诉电脑该如何连接这些点。这张说明书就是索引列表,它会说:“把第 1、第 5 和第 8 号顶点连起来,组成一个三角形”,“把第 5、第 9 和第 8 号顶点连起来,组成下一个三角形”……
    • 三角形网格 (Triangle Mesh):遵循这张“说明书”,电脑将顶点两两相连,最终构成无数个紧密贴合的三角形面片。这些面片组合在一起,就形成了我们所见的 3D 模型的表面,我们称之为三角形网格
  3. 为什么是三角形? 之所以选择三角形作为基本单元,是因为它有几个无可替代的优点:

    • 最简单的多边形:三个顶点就能确定一个面,不能再少了。
    • 稳定性:三个顶点永远处于同一个平面(共面),这保证了渲染时不会出现奇怪的扭曲和“破面”。四边形或更多边的图形则可能不是平的。
    • 万能性:任何复杂的三维曲面,都可以通过足够多的小三角形来无限逼近,模拟出想要的效果。

所以,“第一步:定位”,其本质是将一个具象的物体,通过坐标系、顶点和三角形连接规则,彻底“翻译”成电脑能够理解和处理的纯数字信息——也就是一个“数字蓝图”。

第二步:变形与移动 - 一切皆可“算”

文章配图

想让模型动起来?比如旋转、缩放或者移动?这背后其实是强大的“矩阵运算”在发挥作用。你不需要理解复杂的数学,只要把它想象成一个“魔方”,你下达一个指令,电脑就通过一系列高效的加减乘除,瞬间计算出成千上万个顶点的新坐标。

但这具体是如何在保证物体不变形的前提下做到的呢?

在进入计算细节前,我们必须明确一个核心前提:我们操作的目标是整个物体,而非单个顶点。为了保持物体的形状不发生扭曲,任何变换指令(无论是移动、旋转还是缩放)都必须统一、同步地应用到构成该物体的所有顶点上。我们之所以能只关注顶点,是因为它们已经定义了物体的全部几何结构。这个过程就像指挥一个军训方阵,口令下达给全体,而每个人都执行相同的动作。最终,是 GPU 强大的并行计算能力,让这种对成千上万个顶点进行同步处理的浩大工程,变为了我们眼前流畅的实时画面。

下面的示例将只展示对一个顶点的计算过程,来揭示其背后的数学规则。

  1. 移动(平移)

移动就是在原坐标的基础上进行加减。

  • 目标:将一个顶点 (x, y, z),在 x 轴方向移动 dx,y 轴方向移动 dy,z 轴方向移动 dz

  • 具体公式

  • x 新=x 旧+dx

  • y 新=y 旧+dy

  • z 新=z 旧+dz

  • 示例

    • 我们以物体上的其中一个顶点 (10, 20, 30) 为例。。

    • 我们想让它向右(x)移动 5 个单位,向上(y)移动 10 个单位。所以 dx=5dy=10dz=0

    • 计算:

      • x 新=10+5=15
      • y 新=20+10=30
      • z 新=30+0=30
    • 新坐标(15, 30, 30)

  1. 缩放(变大变小)

缩放就是用原坐标乘以一个倍数。

  • 目标:将一个顶点 (x, y, z),以原点(0,0,0)为中心,在 x、y、z 方向分别缩放 sxsysz 倍。

  • 具体公式

  • x 新=x 旧×sx

  • y 新=y 旧×sy

  • z 新=z 旧×sz

  • 示例

    • 一个顶点在 (10, 20, 30)

    • 我们想让它在 x 方向放大 1.5 倍,y 方向缩小到一半(0.5 倍),z 方向不变(1 倍)。所以 sx=1.5sy=0.5sz=1

    • 计算:

      • x 新=10×1.5=15
      • y 新=20×0.5=10
      • z 新=30×1=30
    • 新坐标(15, 10, 30)

  1. 旋转

旋转使用三角函数 sincos。电脑内置了这些函数的值,可以直接调用。以下是绕着 Z 轴逆时针旋转 θ 度的公式(可以想象成在 x-y 平面上旋转)。

  • 目标:将一个顶点 (x, y, z),绕 Z 轴旋转 θ 度。

  • 具体公式

  • x 新=(x 旧×cos(θ))−(y 旧×sin(θ))

  • y 新=(x 旧×sin(θ))+(y 旧×cos(θ))

  • z 新=z 旧(因为是绕 Z 轴转,所以 z 坐标不变)

  • 示例

    • 一个顶点在 (10, 20, 30)

    • 我们想让它绕 Z 轴旋转 90 度。我们在数学课学过:cos(90°) = 0sin(90°) = 1

    • 计算:

      • x 新=(10×0)−(20×1)=0−20=−20
      • y 新=(10×1)+(20×0)=10+0=10
      • z 新=30
    • 新坐标(-20, 10, 30)

第三步:渲染优化 - 只画“看得到”的,才是最聪明的

文章配图

现在,所有顶点都就位了,但电脑并不会“傻瓜式”地画出每一个三角形。为了让画面更流畅(也就是提高帧率),它会像一个聪明的摄像师一样思考:

  1. “看不见的背面就不画了” 一个不透明的物体,你永远只能看到它朝向你的那一面。电脑会做一个简单的方向判断,把所有背对你的三角形都直接忽略,根本不画它们。
  2. “被挡住的东西也不画” 如果一棵树挡住了一座房子,你只能看到树,看不到树后面的房子。电脑也是这样。它在画每个像素点时,都会“记笔记”,记下这个点上已经画了的物体的远近(z 坐标)。
  • 当它准备画一个新的物体时,会先比较一下:“这个新物体比我已经画在这里的更近吗?”
  • 如果更近:就用新物体的颜色覆盖掉原来的,并更新笔记。
  • 如果更远:那就说明它被挡住了,直接跳过不画。

总结一下: 3D 游戏的每时每刻,电脑都在做三件事:

  1. 几何定位:用 (x, y, z) 坐标描述一个由三角形组成的世界。
  2. 代数运算:用简单的 加减乘除sin/cos 公式,来计算所有顶点移动、缩放、旋转后的新位置。
  3. 逻辑判断:用聪明的“画家”逻辑,只画那些我们最终能看得到的部分。