« PlayStation 硬件架构 (index)

PlayStation 硬件架构

Chapter 4: 图形


目录

  1. 硬件组织
  2. 绘制场景
    1. 指令
    2. 可见性方法
    3. 光栅化
    4. 着色器
    5. 纹理
    6. 剩余步骤
  3. 设计
  4. 玩转 VRAM
  5. 机密与限制
    1. 扭曲的模型/纹理
    2. 自相矛盾的主张
    3. 预渲染的图形
  6. 视频输出

概括地说,图形处理流程的很大一部分是由 GTE 完成的。 其中包括透视变换(利用摄像机的透视将3D空间投射到2D平面上)和光照。 处理后的数据将被发送到索尼专有的GPU上进行渲染。

硬件组织

系统配备1 MB的VRAM,用于存储帧缓冲区、纹理和GPU渲染场景所需的其他资源。 CPU可以使用DMA填充该区域。

配备的芯片(VRAM)是双端口的,就像Virtual Boy的一样。 VRAM使用两条16位总线,可在CPU/DMA/GPU和视频编码器之间同时访问。

Image
使用VRAM的内存布局

Image
使用SGRAM的内存布局

不过在这款游戏机的后期版本中,索尼改用了SGRAM芯片(使用单独32位数据总线的单端口选项)。 嘘!...... 好吧,公平地说,每一种都有其优点和缺点。 可以肯定的是,由于时序上的差异,后来的游戏(如喷气摩托3(Jet Moto 3))在基于VRAM的系统上运行时,会出现图形卡顿的现象。 如果你想了解详情,Martin Korth的"Nocash PSX规格"记录了不同的时序等信息。

绘制场景

如果您一直在阅读世嘉土星的文章,让我告诉您,这款GPU的设计要简单得多

现在,我主要以Insomniac的小龙斯派罗:龙年(Spyro: Year of the Dragon)为例,向大家展示如何绘制场景。 请注意,这款游戏的内部分辨率过于狭窄(292x217像素),导致我无法清晰地剖析游戏的每个阶段,因此我将其放大了一些,以方便演示。 如果你好奇,这里有一个原始比例的样本 。

指令

Image
基本GPU指令流水线

首先,CPU通过向内部64字节FIFO缓冲区填充指令(最多三条),向 GPU 发送几何数据(顶点)。 这些命令可能要求GPU渲染某些内容、更改设置或操作VRAM。

从本质上讲,渲染命令说明了绘制基元的方式和位置。 GPU可以单独绘制线条矩形三角形,后者是构成丰富3D模型的基本要素。

一旦接收到几何图形,就会进行剪切,以跳过对不可见多边形(位于摄像机视角之外)的操作。

基元的位置用指向帧缓冲区的 X/Y 坐标系来表示。 PS1的GPU采用整数坐标模型,每个坐标对应一个像素的中心点(称为采样点)。 换句话说,没有小数坐标。

可见性方法

Image
古惑狼(Crash Bandicoot)(1996) 这款游戏使用预先排序的几何图形来提高性能。 因此,它的摄像头只能向后或向前移动。

竞争对手一样,PS1也不具备任何解决可见性问题的硬件功能。 不过,GPU通过提供一个排序表来处理排序的多边形: 这是一个专用表格,其中每个条目都使用深度值(也称为 "Z值")进行索引,并包含GPU命令所在的地址。

CPU首先需要手动对多边形进行排序,然后将它们引用到表中正确的条目中。 最后,CPU会命令DMA将表格发送到GPU。 这一过程将使GPU能够以正确的顺序渲染几何图形。

此外,还提供了多个DMA函数,以协助CPU和GPU创建和遍历该表。

光栅化

Image
该场景的线框图

一旦命令被GPU解码,就需要将接收到的几何图形(顶点)转换为像素。 这将使系统能够应用纹理映射和特效,并最终将其显示在二维面板(电视或显示器)上。 为此,GPU会分配一个像素矩阵作为工作区,这就是所谓的帧缓冲区。 与更复杂的世嘉土星相比,GPU 只需要一个帧缓冲器。

光栅化器是负责将向量转换为线条、三角形或矩形,然后再转换为像素的单元。 现在,这一过程因所需的基元不同而大相径庭:

对于三角形这个唯一能用来制作纹理的多边形,光栅化器将:

  1. 抓取每个三点顶点并计算边缘。 这样就形成了一个三角形。
  2. 分析三角形区域,确定它们占据了帧缓冲区的哪些像素。 只有覆盖采样点的多边形部分才会变成像素。

生成的像素不会立即写入帧缓冲区。 相反,它们会被发送到流水线的下一阶段进行进一步处理,我们将在下面的段落中看到。

着色器

Image
生效的高洛德(Gouraud)着色

为了在三角形或线条上应用光照效果,GPU提供了两种算法:

之所以有这种选择,是因为平面着色每秒填充的多边形数量是高洛德着色的~2.5倍,因此优化哪些多边形需要比其他多边形更逼真的着色非常重要。

纹理

Image
纹理已应用(嗒哒!

三角形表面还可以与纹理(2D位图)混合,生成最终效果。

GPU执行逆纹理映射,即 GPU 遍历每个光栅化像素,并在纹理贴图中查找其对应的像素(称为纹理元素(Texel))。 纹理元素是通过线性插值纹理贴图(在VRAM中找到)来计算的,以符合多边形的形状。 用于插值的程序称为"仿射纹理贴图",这种技术只使用2D坐标(X-Y值),而忽略了用于透视的第三个坐标(Z或"深度")。

由于纹理贴图很少具有光栅化多边形的精确尺寸,因此可能会出现混叠(不正确的结果)。 这表现为不必要的失真,例如缺失或放大的纹理。 为了解决这个问题,先进的GPU采用纹理过滤技术来平滑(插值)颜色的突然变化。 现在,PS1的GPU没有实现任何过滤功能,因此它采用了一种名为近邻的算法来校正比例,而不会平滑结果。 这种算法速度非常快(而且便宜),但这也解释了为什么纹理模型看起来会"方方正正"。

GPU还包含以下可供使用的特效(在三角形上):

值得一提的是,PS1恰好擅长这些效果!

剩余步骤

完成后,GPU会将像素写入VRAM中的帧缓冲区,然后由视频编码器接收并播放到屏幕上。

设计

让我们从这些理论中解脱出来。 这里有一些为3D时代从头开始设计的游戏角色的例子,它们是可交互的,所以我鼓励你去看看!

3D model 3D model 3D model
"现代版本"中可用的互动模型
小龙斯派罗(Spyro the Dragon)(1998)
413个三角形

3D model 3D model 3D model
"现代版本"中可用的互动模型
古惑狼(Crash Bandicoot) (1996)
732个三角形

玩转 VRAM

利用可用的 VRAM(整整 1 MB),我们可以分配一个1024×512像素、16位色彩的超大帧缓冲区,或者一个960×512像素、24位色彩的逼真帧缓冲区-让我们可以绘制任何游戏都曾展示过的最佳帧...... 这听起来很令人印象深刻,对吧? 不过,这也引发了一些问题:

好吧,那就用16bpp的640x480缓冲区来代替,这样就有424 KB的VRAM用于绘制材质。 到目前为止还不错吧? 同样,这样的分辨率在 CRT 显示器上可能还不错,但在 90 年代每个人家里都有的那种电视上就不那么明显了。 那么,有没有办法优化帧缓冲器呢? 引入可调节的帧缓冲器

Image
NO$PSX调试器上的VRAM可视化。 您可以看到双帧缓冲区和纹理(使用颜色查找表进行翻译,也存储在这里)。

从本质上讲,该游戏机的GPU不需要通过使用"不受欢迎"的分辨率来浪费宝贵的VRAM,而是允许减少帧缓冲区的尺寸,从而有效地增加其他资源的可用空间。 在"Gears Episode 2"中,Halkun展示了一种将640x480帧缓冲区分为两个320x480帧缓冲区的设置,然后依靠一种名为"翻页"(page-flipping)的技术同时渲染多个场景。

翻页技术包括在游戏需要时,在两个可用的帧之间切换显示位置,使游戏可以在显示一个场景的同时渲染另一个场景。 因此,可以隐藏任何闪烁效果,并改善加载时间(玩家肯定会对此表示赞赏!)。

总体而言,Halkun的布局仅消耗600 KB的VRAM。 剩下的部分(424 KB)可用于存储颜色查找表和纹理,再加上2 KB的纹理缓存,这样的设置非常方便高效。

最后值得一提的是,VRAM可以同时使用多种颜色深度进行映射,这意味着程序员可以在24bpp位图(例如FMV框架使用的位图)旁边分配一个16bpp的帧缓冲区。 这是另一项有利于进一步优化空间的功能。

机密与限制

尽管PS1的架构非常简单合适,但问题还是接踵而至。 令人惊讶的是,某些问题却能通过非常巧妙的变通方法得到解决!

扭曲的模型/纹理

Video
Video - 史克威尔(Square)的最终幻想8(Final Fantasy VIII)(1999) 纹理在移动时会有一些抖动

众所周知,用于处理几何图形和应用纹理的例程存在一些误差。

首先,光栅处理器只能处理像素单位:虽然顶点坐标是整数,但计算出的三角形边缘可能只占一个像素的一小部分。 然而,光栅化器只会在三角形区域覆盖像素采样点的情况下绘制像素,而不会跟踪所占的部分。 这就带来了一些问题:

解决这一问题的方法通常是采用亚像素分辨率(sub-pixel resolution),光栅化器从中跟踪每个三角形区域所占像素的分数。 因此,可以添加抗锯齿方法来缓和锯齿状边缘或颜色的突然变化。

接着,排序表要求开发人员/程序按照正确的顺序显示几何图形。 在某些情况下,为了提高性能,执行的计算依赖于过多的近似值。 这可能会导致本应显示的表面闪烁或被遮挡

此外,设置低分辨率的帧缓冲区可能会放大所有这些混叠问题。

最后,正如大家所知,仿射变换没有深度感,当摄像机靠近模型并垂直于观看者时,用户的感知可能会被混淆。 这种效果也被称为纹理扭曲(texture warping)。 因此,一些游戏采用了曲面细分(将大多边形分割成小多边形)来减少失真,而另一些游戏则直接交换纹理,改用纯色。 一般来说,GPU最终会通过实现透视校正来解决这一问题,即使用深度值对纹理进行插值。

自相矛盾的主张

如果你查看其他技术频道或论坛,你会发现关于PS1摇摆/扭曲/失真效果的其他解释。 其中一些与我之前的解释不谋而合,而另一些则会提出不同的观点。 因此,我想就以下说法不准确的原因谈谈我的看法:

模型/纹理晃动是因为缺少FPU

FPU 并不决定计算机是否能进行小数运算。 PS1和其他没有FPU的计算机一样,仍然可以进行定点运算。 此外,使用软件仿真,浮点数也可以计算(只是速度较慢)。 总之,FPU只是加速器,不要将其与ALU(算术逻辑单元,CPU中执行算术运算的关键部分)或十进制数混为一谈。

GPU 的整数坐标系导致模型/纹理晃动

采用整数坐标系是降低GPU计算成本的常用方法。 正是因为没有采用亚像素分辨率,这才成为一个显而易见的问题。 总而言之,如果光栅处理器能够计算三角形所占像素的比例,那么就可以使用抗锯齿技术来平滑色彩的突然变化

缺乏混合映射导致纹理扭曲

实施反纹理映射的GPU(如本机)会出现一种称为"欠采样"的测量误差(一个像素被映射到多个纹理)。 因此,这会产生混叠(错误的结果)。 在渲染距离摄像机较远的几何体时,这种现象非常明显。 为了解决这个问题,现代纹理贴图程序采用了"三线性过滤"技术,即使用存储在不同比例的相同纹理软化色元(mipmaps),并在两者之间进行一些插值。 总而言之,mipmapping是一种解决混叠问题的方法。 它是一种仿射纹理贴图(缺乏透视校正),在三点表面上进行纹理插值,而不考虑深度。 因此会产生"扭曲"效果。

缺乏Z缓冲导致模型/纹理闪烁

带有Z缓冲的GPU可在硬件层面上解决可见表面的确定问题。 PS1依赖于排序表,这意味着开发人员负责确定哪些几何体位于其他几何体之前。 总之,任何显示闪烁三角形的模型都是由排序例程(软件)引起的,因此可以通过相同的软件来解决。

预渲染的图形

Image
史克威尔的最终幻想7(Final Fantasy VII) (1997) 预渲染背景的场景。 模型的互动和移动方式对于_欺骗_用户的感知至关重要。

现在让我们来谈谈"好"的功能...

如果一款游戏想要获得比GPU所能提供的更逼真的场景,一个可行的办法就是堆叠两个三角形,然后使用运动解码器在上面输入预渲染的电影画面。 FMV视频会占用大量空间,幸好CD-ROM为此做了准备。

有些游戏专门依靠它来合成背景,而且老实说,在显像管电视上看这些视频还是很有说服力的,但显然,具有升分辨率功能的现代模拟器很快就能分辨出来。

视频输出

该控制台的第一版带有以下端口,可传输数量惊人的视频信号:

后来的控制台改版取消了这些端口,最后只剩下 "AV多路输出"。


Previous: 3. 中央处理器 (CPU)

Next: 5. 音频


Rodrigo Copetti © 2026 RSS Feed

切换至现代版

主页 · 文章 · 支持 · 关于作者 · 关于此网站