news 2026/10/19 1:13:47

游戏开发术语|帧率、Draw Call、LOD:性能相关术语

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
游戏开发术语|帧率、Draw Call、LOD:性能相关术语

适合阶段:入门
适合读者:刚入行或准备入行的学生、转行者,以及第一次接触性能优化、需要看懂性能分析工具的客户端程序员
说明:文中的数值,如帧时间预算和 Draw Call 数量,仅为便于理解的示意。实际预算取决于目标平台、引擎、渲染管线和项目类型,请以项目实测为准


引子

性能相关的讨论,新人最容易听不懂。项目组里经常有这样的对话:

  • “这个场景掉到 40 帧了,帧时间看看是 CPU 还是 GPU。”
  • “Draw Call 太多了,这些物件能不能合批?”
  • “远处的树换成低 LOD,再远一点直接剔掉。”
  • “Overdraw 太严重了,半透明特效叠了七八层。”
  • “玩十分钟就发烫降频,帧率从 60 掉到 45。”
  • “平均帧率没问题,但 1% Low 很难看,有卡顿。”

这些词背后是同一个问题:在有限的时间和硬件资源内,把一帧画面算完、画完。

这篇文章先讲清楚“一帧里发生了什么”,再按 CPU、GPU、内存、移动端特有问题依次介绍常见术语,最后落到程序员的日常工作:如何测量、如何定位瓶颈、如何避免常见误区。


一、全景:一帧里发生了什么

1. 一帧的大致流程

以常见的游戏引擎为例,一帧的工作大致分为三段:

CPU:主线程(游戏线程) CPU:渲染线程 GPU ┌──────────────────────────┐ ┌──────────────────┐ ┌─────────────────────┐ │ 输入处理 │ │ 剔除(可见性判断) │ │ 顶点处理 │ │ 游戏逻辑、AI、脚本 │→ │ 排序、合批 │→ │ 光栅化 │ │ 物理、动画 │ │ 提交 Draw Call │ │ 像素着色、后处理 │ │ UI 更新 │ │ │ │ 输出到屏幕 │ └──────────────────────────┘ └──────────────────┘ └─────────────────────┘

现代引擎通常让这三段流水线并行:当 GPU 在画第 N−2 帧时,渲染线程在准备第 N−1 帧,主线程在计算第 N 帧。

时间 → 主线程 │ 帧1 │ 帧2 │ 帧3 │ 帧4 │ 渲染线程 │ 帧1 │ 帧2 │ 帧3 │ GPU │ 帧1 │ 帧2 │

这带来一个关键结论:最终帧率由最慢的那一段决定。主线程花 10ms、GPU 花 20ms,帧率就由 GPU 决定,优化主线程不会让帧率提高。

2. 术语速查

类别术语一句话含义
帧帧率(FPS)、帧时间(Frame Time)每秒画多少帧 / 每帧花多少毫秒
卡顿(Hitch / Stutter)、1% Low偶发的长帧 / 最差帧的表现
垂直同步(VSync)、帧节奏(Frame Pacing)与屏幕刷新的配合
瓶颈CPU 瓶颈(CPU Bound)、GPU 瓶颈(GPU Bound)谁拖慢了这一帧
CPU 端Draw Call、SetPass Call、合批(Batching)、实例化(Instancing)向 GPU 提交绘制命令的开销
GC(垃圾回收)托管内存回收造成的停顿
GPU 端面数、顶点数几何复杂度
填充率(Fill Rate)、Overdraw像素处理压力
带宽(Bandwidth)读写显存的数据量
Shader 复杂度、Shader 变体着色程序的计算量与数量
按需降级LOD、Mipmap、HLOD远处用更简单的版本
剔除(Culling)看不见就不画
内存与加载内存预算、纹理压缩、流式加载放不放得下、加载快不快
移动端发热、降频(Thermal Throttling)、功耗能不能持续跑得动

二、帧率与帧时间

1. FPS 与帧时间

帧率(FPS,Frames Per Second):每秒渲染的帧数。
帧时间(Frame Time):渲染一帧所用的时间,通常以毫秒(ms)为单位。

两者互为倒数:帧时间(ms)= 1000 / FPS。

目标帧率每帧时间预算常见场景
30 FPS33.33 ms主机画质模式、部分移动端重度游戏
60 FPS16.67 ms主流动作、射击、竞技游戏
90 FPS11.11 ms部分高刷手机、VR 常见下限
120 FPS8.33 ms高刷手机、主机性能模式、竞技 PC 游戏
144 FPS6.94 ms竞技 PC 显示器

2. 为什么程序员更喜欢说“帧时间”

FPS 不是线性的,帧时间是:

变化FPS 看起来帧时间实际
30 → 25 FPS掉了 5 帧增加约 6.67 ms
60 → 55 FPS掉了 5 帧增加约 1.52 ms
120 → 115 FPS掉了 5 帧增加约 0.36 ms

同样“掉 5 帧”,代价相差近 20 倍。所以:

  • 优化以毫秒计:“这个改动节省了 2ms”比“提升了 8 帧”更准确;
  • 预算以毫秒分配:例如 60 FPS 时,16.67ms 可以拆成逻辑 4ms、物理 2ms、动画 2ms、UI 1ms……

在 Unreal 中,控制台命令stat unit会分别显示 Frame、Game(游戏线程)、Draw(渲染线程)、GPU 的耗时,这正是按帧时间思考的典型工具。

3. 平均帧率会骗人:卡顿与 1% Low

平均帧率 60 的游戏,玩起来可能依然很卡。原因是偶发的长帧:

帧时间(ms) 80 │ █ 60 │ █ 40 │ █ 16 │ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ └──────────────────────────────────→ 帧 ↑ 一次 80ms 的卡顿(Hitch)

这一帧对平均值的影响很小,但玩家能明显感觉到“顿了一下”。

术语含义
卡顿(Hitch / Spike)偶发的、明显超出预算的长帧
抖动(Stutter)帧时间忽长忽短,不稳定
1% Low / 0.1% Low衡量最差帧的指标。常见计算方式有两种:最慢 1% 帧的平均帧率,或第 99 百分位帧时间换算的帧率。不同工具口径不同,对比时要统一

常见卡顿来源:

  • 资源同步加载、Shader 首次编译;
  • GC(垃圾回收);
  • 大量对象同时创建或销毁;
  • 一次性的大计算,如寻路网格重建、大范围物理查询。

一个计算帧时间统计的示意:

defframe_stats(frame_times_ms:list[float])->dict:"""根据帧时间序列计算平均帧率与 1% Low(按最慢 1% 帧的平均值计算)。"""n=len(frame_times_ms)avg_ms=sum(frame_times_ms)/n worst=sorted(frame_times_ms,reverse=True)count=max(1,n//100)# 最慢的 1% 帧worst_avg_ms=sum(worst[:count])/countreturn{"avg_fps":1000/avg_ms,"one_percent_low_fps":1000/worst_avg_ms,"max_frame_ms":worst[0],}

4. 垂直同步、撕裂与帧节奏

术语含义
刷新率(Refresh Rate)显示器每秒刷新的次数,单位 Hz,如 60Hz、120Hz
画面撕裂(Tearing)显示器刷新到一半时帧缓冲被替换,同一画面出现上下错位
垂直同步(VSync)等显示器刷新完成再交换帧缓冲,消除撕裂,但可能增加输入延迟
三重缓冲(Triple Buffering)多一个缓冲区,减少 VSync 下的等待,代价是更多内存和可能的延迟
可变刷新率(VRR)显示器配合游戏的实际帧率刷新,如 G-SYNC、FreeSync、HDMI 2.1 VRR
帧节奏(Frame Pacing)每帧在屏幕上停留的时间是否均匀

帧节奏常被忽视。在 60Hz 屏幕上以 30 FPS 运行,理想情况是每帧显示 2 次刷新(33.3ms)。如果节奏不稳定,实际可能是 16.7ms、50ms 交替出现,平均仍是 30 FPS,但玩家会感到明显的抖动。

Android 提供了 Android Frame Pacing 库(Swappy)帮助处理这一问题,Unity、Unreal 在 Android 平台已集成相关支持。

5. 锁帧与输入延迟

  • 锁帧(Frame Rate Cap):主动限制最高帧率。移动端常见 30 / 60 档位,主机常见“画质模式 30 帧 / 性能模式 60 帧”。锁帧能降低功耗与发热,使帧率更稳定。
  • 输入延迟(Input Latency):从玩家按键到画面响应的时间。帧率越低、流水线越深、缓冲越多,延迟越高。竞技游戏对此尤为敏感。

三、CPU 瓶颈与 GPU 瓶颈

优化的第一步不是“找哪里可以优化”,而是判断瓶颈在哪一端。

1. 两种瓶颈

类型含义常见原因
CPU 瓶颈(CPU Bound)CPU 端处理一帧的时间超过预算,GPU 在等 CPU游戏逻辑复杂、对象过多、Draw Call 过多、GC、物理计算
GPU 瓶颈(GPU Bound)GPU 处理一帧的时间超过预算,CPU 在等 GPU分辨率高、Overdraw 严重、Shader 复杂、后处理过多、面数过高

CPU 瓶颈还可以细分为主线程(游戏线程)瓶颈和渲染线程瓶颈,二者的优化方向完全不同。

2. 快速判断方法

方法看什么
看分析工具直接比较主线程、渲染线程、GPU 各自的耗时,最长的就是瓶颈
降低渲染分辨率帧率明显提升 → 很可能是 GPU 像素处理瓶颈(填充率、Shader、后处理)
分辨率降低但帧率不变瓶颈在 CPU,或 GPU 的顶点处理端
关闭部分逻辑系统如暂停 AI、关闭物理,帧率提升说明主线程是瓶颈
观察等待标记分析工具中主线程大量时间在“等待 GPU / 等待渲染线程”,说明瓶颈在后者

不同引擎中的等待标记名称不同,例如 Unity Profiler 中常见Gfx.WaitForPresent等标记。看到这类标记占用大量时间时,不要误以为是主线程本身慢。

一个关键原则:在 GPU 瓶颈时优化 CPU,或在 CPU 瓶颈时优化 GPU,帧率都不会变化。先定位,再优化。


四、Draw Call 与合批

Draw Call 是新人听到最多、也最容易误解的性能术语。

1. 什么是 Draw Call

Draw Call:CPU 向 GPU 发出的一次“绘制指令”,告诉 GPU 用哪些顶点数据、哪个 Shader、哪些纹理和参数画一批图元。

CPU GPU │ 设置 Shader、纹理、参数(状态切换) │ │ ───────────────────────────────────────→ │ │ Draw Call:画这个网格 │ │ ───────────────────────────────────────→ │ │ 切换材质…… │ │ Draw Call:画下一个网格 │ │ ───────────────────────────────────────→ │

真正贵的往往不是“画”本身,而是 CPU 侧的准备工作:

  • 切换渲染状态(Shader、纹理、混合模式等);
  • 驱动层的校验与命令转换;
  • 引擎侧为每个物体收集数据、设置参数。

因此,Draw Call 过多通常表现为CPU 瓶颈(渲染线程),而不是 GPU 瓶颈。

2. 相关术语

术语含义
Draw Call一次绘制命令
Batch引擎统计的“绘制批次”,在 Unity 统计面板中显示为 Batches
SetPass CallUnity 术语,表示切换 Shader Pass 等渲染状态的次数,通常比 Draw Call 本身更能反映开销
状态切换(State Change)更换 Shader、纹理、混合模式等,开销较大

在 Vulkan、Metal、DirectX 12 等现代图形 API 下,驱动开销显著降低,但 Draw Call 数量和状态切换仍然是需要控制的指标,尤其在移动端。

3. 降低 Draw Call 的常见手段

手段原理适用场景代价
静态合批(Static Batching)把不会移动的物体在构建或加载时合并成大网格场景中的静态建筑、地面物件增加内存和包体,合并后无法单独移动
动态合批(Dynamic Batching)每帧在 CPU 上合并顶点数较少的小物体小型、共享材质的动态物体合并本身消耗 CPU,有顶点数限制
GPU 实例化(GPU Instancing)同一网格、同一材质,一次 Draw Call 绘制多份,每份传入不同参数草、树、石头、大量相同单位要求网格和材质相同
纹理图集(Texture Atlas)多张小图合成一张大图,使多个物体可以共享材质UI、2D 精灵、小型道具图集管理复杂,可能浪费空间
材质合并减少材质种类,让更多物体能合批场景美术规范需要美术配合
引擎的批处理器例如 Unity 的 SRP BatcherUnity URP / HDRP 项目依赖 Shader 写法兼容

注意区分:Unity 的SRP Batcher并不减少 Draw Call 的数量,而是降低相邻 Draw Call 之间的设置开销:使用同一 Shader 变体的物体,其材质数据常驻 GPU,切换时开销更小。所以开启后 Batches 数字可能变化不大,但 CPU 耗时会下降。

Unreal 方面,自 4.22 起重构的网格绘制管线支持对相同网格与材质的自动实例化;UE5 的Nanite虚拟几何体则从根本上改变了几何体的提交方式。

4. UI 的合批

UI 同样产生 Draw Call,而且常被忽视:

问题说明
图集打散同一界面的图片来自不同图集,无法合批
层级穿插图片、文字交替叠放,打断合批
频繁重建以 Unity UGUI 为例,Canvas 中任一元素变化会导致整个 Canvas 重建网格。常见做法是把频繁变化的元素(如倒计时、血条)拆到独立的 Canvas
隐藏方式通过频繁激活 / 禁用对象来隐藏 UI,可能触发重建,具体开销因引擎和 UI 框架而异

5. Draw Call 多少算多

没有通用答案。它取决于平台、图形 API、引擎和每个 Draw Call 的状态切换量。业界经验上,移动端通常比 PC 和主机严格得多。

正确做法是:

  • 在目标设备上测量渲染线程耗时;
  • 以耗时而不是数字本身作为判断依据;
  • 为项目制定自己的预算,并在每日构建中跟踪趋势。

五、GPU 端:面数、填充率、带宽

当瓶颈在 GPU 时,需要区分是“顶点太多”还是“像素太忙”。

1. 面数与顶点数

术语含义
三角面(Triangle / Tris)GPU 渲染的基本图元,模型由大量三角面组成
顶点(Vertex)三角面的角点。因为法线、UV 不同而拆分的顶点,在 GPU 侧会计为多个
顶点着色器开销每个顶点都要经过变换、蒙皮等计算

常见误区:只看建模软件里的面数。实际进入 GPU 的顶点数,会因为硬边、UV 接缝而增加;骨骼蒙皮也会显著增加顶点计算量。

2. 填充率与 Overdraw

术语含义
填充率(Fill Rate)GPU 每秒能处理(写入)的像素数量
Overdraw(过度绘制)同一个像素在一帧中被绘制多次
从侧面看一个像素: 眼睛 ──→ [半透明特效1] [半透明特效2] [半透明特效3] [角色] [地面] ↑ ↑ ↑ ↑ ↑ 这一个像素被着色了 5 次 → Overdraw = 5

不透明物体:GPU 可以通过深度测试(尤其是Early-Z,在像素着色之前做深度测试)提前丢弃被遮挡的像素,因此通常建议从前往后绘制不透明物体。

半透明物体:需要从后往前绘制并混合,无法利用深度测试提前丢弃,每一层都要完整着色。这就是为什么大面积半透明特效、多层 UI 叠加是 Overdraw 的重灾区。

常见优化:

  • 减少大面积半透明粒子,缩小粒子贴图中的透明区域(使用贴合形状的网格而非方形面片);
  • 全屏 UI 打开时,关闭被完全遮挡的 3D 场景渲染;
  • 多数引擎提供 Overdraw 可视化视图,用于定位问题区域。

3. 分辨率:最直接的 GPU 开关

像素数量直接决定像素处理压力:

分辨率像素数(约)相对 1080p
1280 × 72092 万0.44 倍
1920 × 1080207 万1 倍
2560 × 1440369 万1.78 倍
3840 × 2160829 万4 倍

相关技术:

术语含义
渲染分辨率缩放(Render Scale)以低于屏幕的分辨率渲染 3D 场景,再放大显示;UI 通常仍以原生分辨率绘制
动态分辨率(Dynamic Resolution)根据 GPU 负载实时调整渲染分辨率,保持帧率稳定
超分辨率(Upscaling)用算法把低分辨率画面重建到高分辨率,如 NVIDIA DLSS、AMD FSR、Intel XeSS、Apple MetalFX

移动设备的屏幕分辨率往往很高,以原生分辨率渲染 3D 场景通常没有必要。降低渲染分辨率是移动端最常用、也最有效的 GPU 优化手段之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 1:11:50

PTPD 在 QNX 系统上的授时精度验证与误差排查

QNX 上的 PTPD 授时精度验证:从 8 ms 时间戳台阶到百微秒级 概述: QNX 上跑 ptpd2 做 PTP 从时钟,协议显示锁定,不代表时间戳可信。这套平台的原生 socket 时间戳约 8 ms 更新一次,offset 会走台阶;把事件报…

作者头像 李华
网站建设 2026/10/19 1:09:36

STM32多参数检测报警器仿真设计:温度电压电流OLED显示

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/19 1:09:20

厂商Linux内核与驱动定制实战:设备树、probe、裁剪三要素

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/19 1:09:19

ESD干扰下称重数据跳变的整改:耦合路径分析与三管齐下

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/19 1:08:40

基于RK3588的多模态婴儿监护系统:从硬件选型到NPU模型部署实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/19 1:08:37

AI硬件选型周报:边缘推理模组、端侧算力与传感器融合实战经验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华