第 3 章 像素与分辨率:画面的最小颗粒
上一章我们搭好了”坐标”这套地址系统——那条主线你也记住了:现实里的东西是连续的,计算机只认离散的数字,所以工程师必须想办法把”连续”切成”离散”。 坐标那边,是把”无限稠密的空间”变成了能写成数字的格子(连续的实数位置 → 离散的数字坐标)。
这一章,我们把同样的问题搬到”画面”上。你玩的游戏,屏幕上一帧一帧会动的图,到底是由什么拼出来的?为什么有的画面”糊成马赛克”,有的”细腻得像照片”?为什么同一张图在手机上清楚、投到大电视上就糙了?
先问你一个最朴素的观察:
你低头看自己的手机屏幕,凑得非常近,能不能看见上面有无数个小方格子,像瓷砖拼的?你退远一点,那些格子就”消失”了,画面变成一张完整的照片。那些小格子,到底是什么?
它们就是这一章的主角——像素(Pixel)。整本图形教程,都建立在这个”最小颗粒”之上。咱们从它开始,一层层往下扒。
3.1 什么是像素:马赛克的本质
你一定见过”马赛克”——新闻里给车牌、人脸打码,糊成一格一格的方块。那种一格一格的观感,正好就是理解像素的钥匙。
像素,字面意思是”图像的元素”(Picture Element 的缩写)。它是数字图像里最小、不可再分的”一块”。你可以把它想成:一张完整的画面,被工程师用一把看不见的刀,切成了密密麻麻的小方块网格;每个方块内部,只许填一种颜色。
这就引出像素的第一个、也是最本质的特征:它是”一个格子 + 一个颜色”的配对。整张图,就是几百万个这样的配对拼起来的。
3.1.1 连续画面被切成小方块网格
现实里的画面是什么样?是连续的。你看窗外的树,叶子和叶子之间的颜色过渡是丝滑的,没有一条线告诉你”这一块是绿的、下一块是黄的那是边界”。光打在树叶上,颜色是连续渐变的。
但计算机存不了”连续渐变”。声音也是同一个故事(第 9 章会专门讲):连续的声音曲线,被采样成了离散的点。画面走的是一模一样的路:
- 声音:在时间轴上,每隔一小段”拍一张照”,记录那一刻的振幅。
- 画面:在空间上,把整张图切成网格,每个网格(像素)记录”这一格的平均颜色”。
我给你一个扎心的类比,帮它和声音串起来:
声音的采样,是把”时间这条线”切成了一串点;画面的像素,是把”空间这块面”切成了一片格子。一个切的是”时间维度”,一个切的是”空间维度”。两者干的是同一件事——把连续的世界,切成计算机能数的离散单元。
所以第 9 章你会认识”采样率”,这一章先认识”分辨率”——它就是画面在”空间上切得多碎”的指标。两者是一回事,只是一个切时间、一个切空间。这点我们 3.2 细说。
3.1.2 每个像素只许一个颜色,于是有了”马赛克”
为什么切成格子就会有马赛克感?关键在那个限制:一个像素格子里,只能是一种颜色。
想象一片从红到黄的渐变。真实世界里,它每一毫米的颜色都略有不同。但切成格子后,某个格子横跨了”红偏黄”到”黄偏红”这段过渡,怎么办?工程师只能取这格里的一个代表色(比如取中心点的颜色,或者取平均色),填进去。
单个格子很小的时候,这一格的”取一个代表色”误差你看不出来——因为相邻格子颜色接得很近,你的眼睛自动把它们糊成渐变。但格子一大(比如你故意把图片放大,或者码打得很糙),每个格子的”单一颜色”就被你看得清清楚楚,于是出现了那种一格一格的色块——马赛克。
小插曲:你用修图软件把一张小图放大到很大,会看到方块感爆棚。那不是图片”坏了”,是它原本就是由大格子拼的,放大只是把每个格子拉大给你看而已。原始格子细不细,决定了它能放多大而不露馅。
3.1.3 像素在内存里到底是什么
你是写代码的,这个视角你肯定想要。一个像素,在计算机里就是内存里的一组数字——描述”这一格是什么颜色”。
颜色怎么用数字表示?最通用的方式是 RGB:把颜色拆成红(Red)、绿(Green)、蓝(Blue)三个分量,每个分量用一个 0~255 的整数表示亮度。
(255, 0, 0)= 纯红(0, 255, 0)= 纯绿(0, 0, 0)= 黑(255, 255, 255)= 白
所以一个像素 = 三个字节(RGB 各一字节),或者加一个透明度 A 变 RGBA 四个字节。整张图,本质就是一个二维数组:pixel[y][x] = (R, G, B)。
你用代码读一张图,拿到的就是这么一个大数组。屏幕要显示时,显卡把这个数组按位置”贴”到屏幕上对应的格子——第 [x][y] 个格子,显示第 [x][y] 组颜色。
看到没?像素、分辨率、帧,最后全落回你最熟的东西:数组和循环。这也是我反复说的——图形学不是玄学,它的底层是”一串数字 + 一堆数学”,只不过这串数字被你眼睛当成了画面。
3.1.4 像素的颜色也有”位深”:和声音同源的另一刀
你写代码都知道,一个整数用几位存,精度天差地别。像素的颜色也一样,前面我说 RGB 每个分量 0~255(一字节),那叫 8 位每通道(8-bit per channel)。
但颜色也可以更细:
- 8 位/通道(24 位色):常见屏幕,每通道 256 级,共约 1677 万色。够用。
- 10 位/通道(30 位色):专业显示器、HDR,每通道 1024 级,渐变更顺滑,看不到”色带”(banding,大片同色区域里因为等级不够出现的断层)。
- 更低位(比如每通道 4 位):颜色糙,出现明显色块,像老式网页 GIF。
注意这和声音的第 9 章完全对得上:声音有位深(16bit/24bit 决定振幅精度),像素颜色也有位深(决定颜色精度)。两者都是”把连续量量化到有限等级”留下的精度——等级不够,声音有底噪,画面有色带。又一次”连续→离散”的同源伤疤。
为什么游戏美术特别在意这个?因为天空、水面这种大面积缓慢渐变的区域,一旦位深不够,你会看见一条条颜色的”台阶”(色带),非常出戏。HDR 管线(高动态范围)把颜色精度提上去,渐变才干净。
3.2 分辨率与屏幕尺寸:为什么 1080p 手机和电视观感不同
现在你懂了”像素是格子”。那”分辨率”是什么?
分辨率(Resolution),就是这张网格有多少行、多少列。 比如 1920 × 1080,意思是横向 1920 个像素、纵向 1080 个像素,一共约 207 万像素(约”两百万像素”,2 megapixels)。
3.2.1 “像素数量”和”屏幕大小”是两件事
这里有个新手必踩的坑,我得先点破:
你以为”分辨率越高 = 越清楚”,对,但只说对一半。分辨率说的是”格子总数”,屏幕大小说的是”这块玻璃的物理尺寸”。这两件事,经常被人混为一谈。
关键事实:同样的 1080p(207 万像素),贴在一块 6 英寸的手机屏上,和贴在一块 55 英寸的电视上,格子总数是一样的——但每个格子在物理上大小差了十倍。
手机屏小,207 万个格子挤在巴掌大的地方,每个格子小到你的眼睛在正常距离根本分辨不出单个格子,于是画面”细腻如照片”。电视屏大,207 万个格子摊在一米多宽的玻璃上,每个格子被拉大,你坐近了就能看见格子边界,画面就”糙、有颗粒感”。
3.2.2 PPI / 像素密度:把”数量”和”尺寸”归一
工程师用一个指标来统一描述这种差异,叫 PPI(Pixels Per Inch,每英寸像素数),也叫像素密度。
- PPI = 总像素数 ÷ 屏幕物理尺寸(具体是算对角线上的密度,但思想就是”一英寸里塞了多少个格子”)。
- 手机常见 400~500 PPI:一英寸里四五百个格子,密得吓人,肉眼根本看不出格子。
- 普通 1080p 电视约 40 PPI:一英寸才 40 个格子,稀疏,近看就露馅。
一句话记住:“像素”是数量,“清晰”是密度(PPI)。 同样是 207 万个像素,“塞进小屏”密度高所以清晰,“摊在大屏”密度低所以糙。
这就是为什么游戏机和同一个 1080p 信号,接小显示器清楚、接大电视发毛——不是信号变了,是格子被拉大了。
3.2.3 那游戏开发要管分辨率吗
要,而且很要命。两个相关概念你先记着:
第一,渲染分辨率。 游戏每帧要在”一块虚拟画布”上画画面,这块画布多大(多少像素),就是渲染分辨率。你显卡弱,就把渲染分辨率调低(比如从 1080p 降到 720p),格子变少,每帧要算的颜色变少,就流畅了——代价是画面变糙。这是性能和清晰度的经典权衡。
第二,设备适配。 你的游戏要跑在手机(高 PPI 小屏)和电脑(低 PPI 大屏)上,同样一张图,在高 PPI 屏上看起来小且清晰,在低 PPI 屏上看起来大且糙。所以美术做贴图、做 UI,得考虑”在不同像素密度下,元素要多大才既不糊也不挤”。这就是你以后会听到的 DPI 适配 / 多倍图(@2x @3x) 的由来——给高密度屏准备更细的图,免得被拉成大格子露馅。
生活类比:分辨率像”一份菜谱写的份量”(总共几两料),屏幕大小像”装这盘菜的盘子”(大盘小盘)。同样的料,装小盘——每口都饱满精致;装大盘——摊薄了,一口尝不出味。PPI 就是”每平方厘米铺了多少料”的密度。
3.2.4 别漏了”比例”:宽高比(Aspect Ratio)
分辨率还有个常被忽略的孪生概念:宽高比,就是”横向像素数 ÷ 纵向像素数”。1920÷1080 = 1.78,俗称 16:9;老电影 4:3;电影感 21:9。
为什么你该关心它?因为同一分辨率,比例错了画面会被拉伸变形。如果你把一张 16:9 的图硬塞进 4:3 的屏(或反过来),人物会被压扁或拉长,像照哈哈镜。游戏引擎渲染前必须知道目标屏的比例,按正确比例”构图”,否则出来的世界就是歪的。
生活类比:你用一张宽照片去填满一个瘦长相框,要么裁掉两边,要么被拉变形。工程师的处理是”按目标比例重新取景(camera 的 aspect)“,而不是暴力拉伸——这就是宽高比参数存在的意义。
3.2.5 一个反直觉的结论:密度比数量更决定观感
我把 3.2 收个尾,给你一句能直接用在工作里的判断:
买屏幕、调画质时,别只看”分辨率数字多大”,要看”在多大尺寸的屏上、铺出多高 PPI”。 一块 4K 屏如果大到 65 寸,PPI 反而可能不如一块 2K 的 27 寸屏——后者看着更细。分辨率是”总量”,PPI 才是”你实际感受到的清晰”。
游戏里做画质档位(低/中/高/极致),调的”分辨率”那一项,本质是调”每帧算多少个像素”。低端机降分辨率保帧率,高端机拉满分辨率保清晰——同一套逻辑,绕回 3.3 那笔账。
3.3 帧率:流畅感的物理来源
分辨率管的是”空间上切多碎”。现在说”时间上切多碎”——这就要聊帧率(Frame Rate)。
3.3.1 动起来的画,其实是”一堆静画在快速翻”
你小的时候有没有玩过”手翻书”(flip book)?每页画一个小人,姿势差一点点,你快速翻页,小人就动起来了。电影、游戏、动画,全都是这个原理——没有真的”动”,只有”很多张静画,以足够快的速度切换”,骗你的大脑以为在动。
每张静画,叫一帧(Frame)。每秒切换多少张,就是帧率,单位 fps(frames per second,每秒帧数)。
3.3.2 为什么慢了就卡:你的眼睛在”抓帧”
你的大脑有个特性:当画面切换慢到一定程度,你就不再觉得”连续在动”,而是能看清每一张静画之间的跳跃——这就叫”卡顿”。
经验上:
- 15 fps 以下:明显卡,你能数得清画面在跳。早期幻灯片、老游戏机。
- 30 fps:能接受,大部分主机游戏、电影(电影本质是 24 fps,靠运动模糊补足)的底线。不卡,但快速转头时还能察觉不顺。
- 60 fps:丝滑,主流 PC 游戏的追求。画面切换快到你完全”融化”进连续感。
- 120 / 144 fps:电竞级,快速操作下更跟手,职业玩家敏感。
3.3.3 帧率 = 画面的”采样率”,时间被离散化了
我又要拉回那条主线了,你肯定能接上:
声音是把”连续的时间”采样成点(采样率 Hz)。画面动画,是把”连续的运动过程”采样成一帧一帧的静画(帧率 fps)。帧率,就是”画面在时间上的采样率”。
- 采样率太低(8kHz):声音发闷、高频丢失(第 9 章会讲)。
- 帧率太低(15fps):运动发跳、不连贯。
两者是同一个病:时间被切成离散的段后,段与段之间的”真实变化”被丢了,于是你感知到断裂。
这就是第 1 章”餐厅”比喻里那个 16 毫秒的由来:要 60 fps,引擎只有 1/60 ≈ 16.6 毫秒 去算完一整帧(更新世界 + 算画面 + 算声音)。这 16 毫秒,就是”一次上菜”的时间预算。超了,这一帧就晚送达,帧率掉,你就觉得卡。
所以”卡”不是画面本身的错,是引擎没在预算内把下一帧算出来,导致”翻页”变慢。所有优化(减面数、省光照、偷工减料)的终极目标,都是”别让一帧的活儿超过 16 毫秒”。
3.3.4 分辨率、帧率一起压,就是显存和算力的双重账单
把 3.2 和 3.3 合起来,你就能算一笔账:
一帧画面要显示多少个像素 = 横向分辨率 × 纵向分辨率。1080p 是 207 万像素,4K 是 830 万像素(约 4 倍)。
要 60 fps,意味着每秒要把 207 万 × 60 = 1.24 亿个像素的颜色都算出来、送出去。分辨率翻倍,每秒要算的像素量翻倍;帧率翻倍,又要翻倍。这就是”高分辨率 + 高帧率”为什么吃显卡——它不是在算一个画面,是在算一亿多个像素的颜色,每秒重复 60 次。
你写代码时优化一个 O(n²) 循环就头疼,现在想想显卡每帧在做 O(像素数 × 物体数) 的大循环,每秒 60 次——你就懂为什么”面数""分辨率”是性能命门了。
3.3.4 帧率之外的坑:掉帧比”低帧率”更难受(帧 pacing)
我多说一句你以后一定会踩的坑:平均帧率高,不代表一定顺。 真正折磨人的是”忽高忽低”——这一秒 60 帧,下一秒突然掉到 20 帧又弹回 60。
这种”抖动”比稳定 30 帧还难受。因为你的大脑适应了某种节奏,突然一顿,你立刻察觉。它叫 帧 pacing(帧节奏)问题。原因常是:某一帧恰好要算一个特别贵的特效,超时了,于是那一张”晚点到”,造成一次肉眼可见的卡顿(微卡,micro-stutter)。
工程师的应对(你只需要知道名字,以后深究):尽量让每一帧的耗时均匀,而不是有的帧 5 毫秒、有的帧 30 毫秒。这又回到第 1 章餐厅比喻——不是”平均 16 毫秒上齐”,而是”每一道都别突然拖堂”。均匀,比平均值更重要。
3.3.5 垂直同步(VSync)与撕裂:帧率和屏幕的”握手”
还有一个和第 1 章”16 毫秒预算”直接相关的现实问题:屏幕不是随时能收新画面的,它有自己的刷新节奏。
屏幕(显示器)按固定频率刷新,比如 60Hz 屏每 16.6 毫秒”扫”一遍把新像素画上去。如果显卡算完一帧的时机,正好卡在屏幕扫到一半——屏幕上半用了旧帧、下半用了新帧,你就看到画面”错位撕裂”(screen tearing)。关掉同步(无 VSync)帧率能拉高,但可能撕裂;开垂直同步(VSync)让显卡等屏幕扫完再送,不撕裂了,但显卡得”等”,可能反而掉帧、增加输入延迟。
现代解法是 G-Sync / FreeSync 这类自适应同步:让屏幕的刷新节奏跟着显卡出帧的节奏走,两边握手,既不撕裂也不硬等。你以后在引擎里看到 VSync 开关,就知道它管的是”显卡出帧”和”屏幕收帧”的握手时机,本质是帧率与屏幕刷新率的对齐问题。
这又把帧率从”一个孤独的数字”拉回了系统:帧率不是越高越好,要和屏幕刷新率、同步策略一起看。但万变不离其宗——一切为了”在你能感知的阈值内,均匀地把连续运动还原出来”。
3.4 像素也是”连续→离散”的牺牲品
这一节,我要把全教程的哲学给你焊死。这条主线你其实已经见过两次了(第 1 章的“近似与假效果”、第 2 章的“连续坐标落进离散数字”):现实连续,计算机离散,工程师用感知弱点来压缩。
像素,是这条哲学在”空间”上的体现;帧率,是它在”时间”上的体现。而声音的采样量化,是它在”振幅/时间”上的体现。三者同一个祖宗。
3.4.1 像素丢了什么:格子之间的”真实过渡”
声音采样,丢了采样点之间的振幅(用直线连接近似);量化,丢了振幅的精确小数(用最近等级近似)。
画面像素,丢的是格子之间的连续颜色过渡,用”每格一个代表色”近似。你把脸放大看,会发现鼻梁到脸颊的颜色是被一格一格”跳”过去的,不是真的连续。只是格子够细,你的眼睛懒得追究。
这就是马赛克、锯齿(aliasing,物体边缘的台阶状) 的根源——它们都是”连续被切成离散”留下的疤痕。后面讲抗锯齿(anti-aliasing),本质就是”在格子边缘多算几个混合色,骗眼睛以为边界是斜的而不是台阶”,依然是同一套补丁。
3.4.2 为什么工程师敢这么”糊弄”:感知弱点
你可能会问:切得这么碎,丢这么多东西,画面不会假吗?
答案是:人眼有弱点,工程师专门利用它。
- 人眼对”高频细节”(快速变化的细小图案)不敏感,尤其在运动时——所以动画可以少算格子(低分辨率),你运动时看不出来(动态分辨率缩放,就是这思路)。
- 人眼对”亮度”敏感、对”颜色”没那么敏感——所以视频压缩(第 10 章会讲)敢把颜色信息砍掉一大半,你看着差不多。
- 人眼对”快速切换的静画”会自动脑补成连续运动——所以 24/30/60 fps 就够骗你”在动”,不用真去算无限连续的 motion。
一句话:所有”连续→离散”的代价,都被”人眼的感知盲区”接住了。 这不是偷懒,是算准了”你反正看不出来”之后的最优解。声音那边同理——奈奎斯特定理就是你”听不出来”的数学保证。
3.4.3 回到主线,三章连成一条线
你现在已经握住了教程最底层的那根绳:
| 现实(连续) | 离散化手段 | 留下的参数/代价 | 利用的感知弱点 |
|---|---|---|---|
| 声音(振幅随时间连续) | 采样 + 量化(第 9 章) | 采样率、位深、声道 | 奈奎斯特:高频听不到 |
| 画面空间(颜色连续渐变) | 切成像素网格(本章) | 分辨率、PPI | 格子细到看不出 |
| 画面时间(运动连续) | 切成帧(本章) | 帧率 fps | 静画快翻=连续运动 |
看到这张表,你应该有一种”原来全通了”的感觉。游戏引擎里每一个”看起来很技术”的参数,往上数三层,都能追到一个自然现象和一个你想利用的人类感知弱点。 这就是这本教程教你的”概念地图”——不是背参数,是追根。
下一章我们进 3D 世界的积木:三角形与网格。你会发现,连”3D 物体”本身,也是被切成离散小片(三角形)拼出来的——又是一个”连续→离散”。这绳子会一直牵着你走完全书。
3.4.4 一个会算账的小练习:像素要吃掉多少显存
你写代码都知道,数组多大,内存就占多少。像素也是。我给你算一笔账,让你对”像素”有体量感:
一张 1920×1080 的图,每个像素 RGBA 四字节:
- 1920 × 1080 × 4 ≈ 830 万字节 ≈ 8.3 MB。这还只是一张静图。
游戏运行时,屏幕上那”一帧”的像素缓冲(framebuffer,显卡里存当前画面的一整块内存),就是这么大。如果开 4K(3840×2160),一帧就 ≈ 33 MB。60 fps 意味着每秒要新写 33 × 60 ≈ 2 GB 的像素数据进缓冲再读出来显示——这就是为什么显卡要有巨宽的内存带宽,也是为什么”动态分辨率”敢在卡的时候偷偷降分辨率:少算一大半像素,显存带宽压力骤减。
再想贴图(第 5 章主角):一个 2048×2048 的贴图,未压缩四字节就是 16 MB。场景里几百张贴图,全塞显存,显存(你第 1 章就听我说”是金子”)立刻见底。所以后面讲贴图压缩,根子就在这一笔账上——每个像素都是真金白银的显存。
你看到”像素”两个字,脑子里现在应该同时冒出:它是网格里一格颜色,它是数组里一组数字,它也是显存里几字节的账单。三重身份合一体,这就是它”最小颗粒”的分量。
3.5 先收住,回头看三句话
按本教程固定套路,每章结束前你该能回答这三句:
- 这个东西在现实世界里对应什么? 像素对应”连续画面被切成小方块网格,每格一个颜色”;帧率对应”连续运动被切成静画快速翻”。
- 没有它会出什么岔子? 不离散化,计算机存不下、算不了画面;离散太粗,就马赛克、卡顿、发闷。
- 引擎给了哪几个旋钮来对付它? 渲染分辨率、PPI/设备适配、帧率(目标 fps)、宽高比、颜色位深、VSync。每个 knob 都对应一个具体的问题。
记住这条线,下一章见。
【思考题】
- 像素和声音的”采样点”在本质上有哪一点相同?分别是在哪个维度上把”连续”切成”离散”的?
- 同样都是 1080p,为什么手机上清楚、大电视上发糙?“分辨率”和”清晰度”是一回事吗?
- 帧率为什么可以类比成”画面在时间上的采样率”?15 fps 卡顿,和 8kHz 采样声音发闷,是同一种病吗?
- 工程师敢把画面切成格子、把声音切成点,底气来自哪里?举一个”人眼/人耳感知弱点被利用”的例子。
【参考答案】
- 相同点:都是把连续的现实切成离散的、计算机能存数的单元。声音是在”时间维度”上,每隔一小段取一个振幅点(采样率);像素是在”空间维度”上,把整张画面切成小格子,每格取一个代表色(分辨率)。一个是切时间线,一个是切空间面,动作同源。
- 因为分辨率只表示”格子总数”,屏幕大小表示”玻璃物理尺寸”,两者独立。同样 207 万格子,塞进小屏→每个格子极小→PPI 高→肉眼看不见格子→清楚;摊进大屏→每个格子被拉大→PPI 低→近看见格子→发糙。分辨率≠清晰度:清晰度是密度(PPI = 像素数 ÷ 尺寸),分辨率只是数量。
- 是。动画是把”连续的运动过程”采样成一帧帧静画,每秒帧数(fps)对应每秒采样点数(Hz);采样太稀,段间真实变化丢失→你感知到断裂。15fps 卡顿(运动跳跃)和 8kHz 声音发闷(高频丢失),是同一种病:时间被离散化后,段间信息丢了,绕过你的感知阈值就露馅。区别只在一个是空间运动、一个是频率。
- 底气是人眼的感知弱点:对足够细的格子、足够快的翻页、不敏感的颜色/高频,人脑会自动脑补或根本察觉不到。例子:动态分辨率(运动时降分辨率你察觉不到)、视频压缩砍颜色信息你看着差不多、24fps 电影靠运动模糊让你觉得连贯——都是”算准了你反正看不出来”后的最优近似。