Appearance
图形学与渲染 共100题
说明:
- 渲染管线、MVP、深度测试、Early-Z、前向/延迟渲染、DrawCall、透明排序、PBR、ShadowMap、抗锯齿等方向。
题型统计
| 题型 | 数量 |
|---|---|
| 单选题 | 35 |
| 多选题 | 20 |
| 判断题 | 15 |
| 填空题 | 10 |
| 代码阅读题 | 10 |
| 代码填空题 | 5 |
| 简答题 | 3 |
| 场景分析题 | 2 |
| 合计 | 100 |
一、单选题
1. 简化图形渲染管线中,较合理的顺序是?
A. 顶点处理 -> 裁剪 -> 光栅化 -> 片元处理 -> 深度/混合
B. 片元处理 -> 顶点处理 -> 光栅化
C. 深度测试 -> 顶点输入 -> 光栅化
D. 网络同步 -> 材质导入 -> 音频混音
答案:A
解析:渲染管线通常先处理顶点,再把图元光栅化为片元,随后进行片元着色和输出合并。

2. 顶点着色器主要处理的是?
A. 每个顶点的位置和顶点属性
B. 每个像素的最终颜色
C. 网络包序列号
D. 音频采样点
答案:A
解析:顶点着色器按顶点执行,常做坐标变换并输出插值属性。
3. 片元/像素着色器的执行次数主要取决于?
A. 光栅化后产生的片元数量
B. 模型顶点数固定等于片元数
C. C++ 文件数量
D. 贴图文件名长度
答案:A
解析:片元数量与屏幕覆盖面积、分辨率、overdraw、MSAA 等有关。
4. MVP 矩阵中的 M 通常表示?
A. 模型从本地空间到世界空间的变换
B. 相机投影
C. 纹理采样
D. 混合模式
答案:A
解析:Model 矩阵把对象本地坐标变到世界坐标。
5. View 矩阵通常表示?
A. 从世界空间到观察/相机空间的变换
B. 从屏幕到纹理空间
C. 从法线贴图到 albedo
D. 从 UDP 到 TCP
答案:A
解析:View 矩阵相当于相机世界变换的逆变换。
6. Projection 矩阵主要用于?
A. 把观察空间映射到裁剪空间并引入透视投影
B. 创建对象池
C. 压缩音频
D. 排序字符串
答案:A
解析:透视投影会让远处物体在屏幕上更小。
7. 透视除法通常指?
A. 裁剪空间坐标除以 w 得到 NDC
B. 颜色除以 alpha
C. 贴图除以 mipmap
D. CPU 除以 GPU
答案:A
解析:透视除法将齐次坐标转换到归一化设备坐标。
8. Viewport Transform 的作用是?
A. 把 NDC 映射到屏幕/视口坐标
B. 把材质变成 mesh
C. 把音频变成立体声
D. 把纹理变成 shader
答案:A
解析:视口变换决定最终落到屏幕哪个像素区域。
9. 深度测试主要解决?
A. 遮挡关系
B. 音频混响
C. 内存泄漏
D. 网络丢包
答案:A
解析:深度缓冲记录深度,用于判断片元是否被前面的物体挡住。

10. Early-Z 的主要价值是?
A. 尽早丢弃被遮挡片元,减少片元着色开销
B. 增加 DrawCall 数量
C. 让透明排序自动正确
D. 替代所有光照
答案:A
解析:若渲染状态允许,硬件可在片元着色前进行深度拒绝。
11. Z-Prepass 通常指?
A. 先只写深度,再正式渲染颜色
B. 先渲染透明再渲染天空盒
C. 先播放音频再渲染
D. 先上传日志再打包
答案:A
解析:深度预通过可减少复杂 shader 的 overdraw,但会增加一次几何提交。
12. 背面剔除主要依据?
A. 三角形顶点绕序和相机朝向
B. 纹理文件大小
C. 脚本执行顺序
D. 网络 RTT
答案:A
解析:图形 API 可根据顺/逆时针绕序判断正面,剔除背面减少光栅化。
13. DrawCall 过多通常首先增加?
A. CPU 提交渲染命令压力
B. 键盘输入压力
C. 磁盘格式化次数
D. 端口数量
答案:A
解析:DrawCall 涉及状态设置和命令提交,过多容易造成 CPU 端瓶颈。

14. 材质切换通常会影响合批,是因为?
A. 渲染状态不同可能需要拆分提交
B. 材质会删除顶点
C. 材质只影响声音
D. 材质只能用于 UI
答案:A
解析:不同 shader、贴图、关键字和渲染状态都可能打断 batch。
15. 图集 atlas 常用于降低?
A. 纹理切换和 DrawCall 拆分
B. 网络延迟
C. 脚本数量
D. 协程数量
答案:A
解析:多个小图合到同一纹理,能减少材质/贴图切换。
16. Overdraw 指的是?
A. 同一屏幕区域被多次绘制
B. 同一 C++ 函数被多次重载
C. 网络包重复发送
D. 音频重复播放
答案:A
解析:透明特效、UI 叠层和大面积半透明面片容易造成 overdraw。
17. 透明物体常需要注意排序,是因为?
A. 混合结果与绘制顺序有关
B. 透明物体没有顶点
C. 透明物体不能有材质
D. 透明一定不参与渲染
答案:A
解析:常规 alpha blending 不满足交换律,顺序会影响最终颜色。

18. 不透明物体常见排序倾向是?
A. 尽量前到后以利用深度拒绝
B. 一定后到前
C. 完全随机
D. 必须按对象名字
答案:A
解析:前到后有利于 Early-Z 减少后续片元着色。
19. 透明物体常见排序倾向是?
A. 后到前绘制,且通常关闭深度写入
B. 前到后并强制写深度
C. 随机排序
D. 只按材质名字排序
答案:A
解析:半透明混合常依赖后到前累积颜色。
20. 前向渲染在多光源场景下的一个常见问题是?
A. 光源多时 shader/pass 成本可能上升
B. 不能渲染不透明物体
C. 不能使用纹理
D. 不能有相机
答案:A
解析:前向渲染通常在物体着色时直接计算光照,光源数量会影响成本。
21. 延迟渲染的核心中间结果是?
A. G-Buffer
B. TCP Buffer
C. Audio Buffer
D. Input Buffer
答案:A
解析:G-Buffer 保存位置/法线/材质等信息,之后再做光照。
22. 延迟渲染的常见缺点是?
A. G-Buffer 带宽/显存压力大,透明处理不方便
B. 不能使用相机
C. 不能用法线
D. 只能渲染 2D
答案:A
解析:延迟渲染更适合大量动态光照,但透明、MSAA、带宽都是常见问题。
23. MSAA 主要减少的是?
A. 几何边缘锯齿
B. CPU 内存泄漏
C. 网络抖动
D. 音频噪声
答案:A
解析:MSAA 对边缘采样更有效,对 shader 内部高频纹理锯齿帮助有限。
24. SSAA 的特点是?
A. 高分辨率渲染后下采样,质量高但成本高
B. 只采样边缘
C. 只影响音频
D. 只减少 DrawCall
答案:A
解析:SSAA 直接增加渲染分辨率,代价明显。
25. 法线贴图主要用于?
A. 用纹理扰动法线表现细节
B. 存储 TCP 包
C. 删除顶点
D. 替代所有光照
答案:A
解析:法线贴图能在低面数模型上表现细节光照。

26. 切线空间法线贴图通常需要哪些顶点基向量?
A. Tangent、Bitangent、Normal
B. Position、Scale、Time
C. TCP、UDP、HTTP
D. Audio、Pitch、Volume
答案:A
解析:TBN 矩阵用于把切线空间法线转换到目标空间。
27. Lambert 漫反射核心项通常是?
A. max(dot(N, L), 0)
B. min(distance, 0)
C. alpha + beta
D. hash(key)
答案:A
解析:表面越朝向光源,dot(N,L) 越大。
28. Blinn-Phong 高光通常使用哪个向量?
A. 半程向量 H
B. 网络方向
C. 纹理尺寸
D. 对象 ID
答案:A
解析:Blinn-Phong 使用视线方向和光照方向的半程向量计算高光。
29. PBR 中 roughness 增大通常会让高光?
A. 更宽、更暗、更粗糙
B. 更窄、更亮且像镜面
C. 完全不受影响
D. 变成网络包
答案:A
解析:粗糙度越高,微表面法线分布越分散。
30. ShadowMap 的基本思路是?
A. 从光源视角记录深度,再从相机视角比较
B. 从音频源采样
C. 从网络包里读取阴影
D. 只靠顶点颜色
答案:A
解析:光源深度图用于判断当前点是否被挡住。

31. Shadow Acne 常见缓解方式是?
A. 使用深度偏移 bias
B. 删除所有阴影
C. 增加网络带宽
D. 关闭相机
答案:A
解析:深度精度和自遮挡会导致阴影痤疮,bias 可缓解但过大产生 Peter Panning。
32. Shader 中大量动态分支可能影响性能,主要因为?
A. 同一波前/warp 内分支发散会降低并行效率
B. 分支会删除贴图
C. 分支会阻止编译
D. 分支只在 CPU 执行
答案:A
解析:GPU 以 SIMD/SIMT 方式执行,分支发散会让不同路径串行化。
33. Mipmap 的主要作用是?
A. 降低远处纹理采样闪烁并改善缓存/带宽
B. 提高网络吞吐
C. 替代法线
D. 增加三角形数量
答案:A
解析:远处使用低分辨率 mip 可减少高频走样。
34. Gamma 校正主要处理的是?
A. 线性空间计算与显示空间编码之间的关系
B. A* 启发函数
C. 对象池容量
D. TCP 拥塞窗口
答案:A
解析:光照计算应在线性空间进行,再转换到显示相关空间。
35. Frame Debugger 主要用于?
A. 逐步查看渲染事件、DrawCall 和状态
B. 查看 DNS 缓存
C. 编辑音频
D. 替代编译器
答案:A
解析:Frame Debugger 能帮助定位渲染顺序、材质、合批和状态问题。
二、多选题
1. 渲染管线中常见阶段包括?
A. 顶点处理
B. 光栅化
C. 片元/像素处理
D. 深度/模板/混合
答案:A、B、C、D
解析:这些都属于图形渲染流程中的关键阶段。
2. 下列哪些属于常见坐标空间?
A. 模型空间
B. 世界空间
C. 观察空间
D. 裁剪空间
答案:A、B、C、D
解析:顶点会经历多个空间变换直到屏幕空间。
3. 可能造成 GPU 压力的因素有?
A. 过多 overdraw
B. 复杂 fragment shader
C. 大纹理带宽
D. 过高分辨率
答案:A、B、C、D
解析:GPU 压力常来自填充率、shader、带宽和分辨率。
补充考法:旧文件中将 C++ 函数重载 作为干扰项;图形渲染的 GPU 压力通常更关注 overdraw、fragment shader、纹理带宽、分辨率和后处理。

4. 减少 DrawCall 的常见方式有?
A. 静态/动态合批
B. GPU Instancing
C. 图集
D. 每个对象单独材质实例
答案:A、B、C
解析:单独材质实例通常会破坏批处理。
补充考法:旧文件强调 减少材质切换,本质是减少渲染状态变化;而给每个物体创建独立材质通常会破坏合批。

5. 影响合批的常见因素有?
A. 材质不同
B. Shader 关键字不同
C. 渲染队列不同
D. 纹理不同
答案:A、B、C、D
解析:状态不一致往往需要拆分批次。
6. 关于矩阵变换,正确的有?
A. Model 把本地坐标变到世界坐标
B. View 与相机有关
C. Projection 与投影有关
D. Viewport 把坐标映射到屏幕区域
答案:A、B、C、D
解析:这是图形学坐标变换的基本链路。
补充考法:旧文件把 矩阵乘法顺序无所谓 作为干扰项;矩阵乘法通常不满足交换律,MVP 顺序必须和行/列向量约定一致。

7. 深度测试相关说法正确的有?
A. 可解决遮挡
B. 依赖深度缓冲
C. 可减少被遮挡片元输出
D. 对透明排序没有任何限制
答案:A、B、C
解析:透明混合仍然有排序和深度写入问题。
8. 透明渲染常见问题有?
A. 顺序相关
B. 深度写入容易遮挡后续透明
C. 多个透明层难精确排序
D. 永远比不透明更快
答案:A、B、C
解析:透明通常更容易 overdraw,未必更快。
9. 前向渲染的特点可能包括?
A. 透明处理相对直接
B. 多光源成本可能高
C. 材质表达直观
D. 必须使用 G-Buffer
答案:A、B、C
解析:G-Buffer 是延迟渲染核心,不是前向必需。
10. 延迟渲染的特点可能包括?
A. 适合大量动态光源
B. 需要 G-Buffer
C. 带宽/显存压力较大
D. 透明处理较麻烦
答案:A、B、C、D
解析:这些都是延迟渲染常见取舍。

11. 抗锯齿方法包括?
A. MSAA
B. SSAA
C. TAA
D. FXAA
答案:A、B、C、D
解析:它们分别从多采样、超采样、时间累积、后处理等角度处理锯齿。
12. PBR 常见贴图或参数包括?
A. Albedo/BaseColor
B. Metallic
C. Roughness/Smoothness
D. Normal
答案:A、B、C、D
解析:PBR 材质通常由颜色、金属度、粗糙度、法线等控制。
13. ShadowMap 常见问题包括?
A. Shadow Acne
B. Peter Panning
C. 锯齿
D. 级联切换痕迹
答案:A、B、C、D
解析:阴影质量受深度精度、分辨率、bias、级联划分影响。
14. 移动端渲染优化常见方向有?
A. 降低 overdraw
B. 降低 shader 复杂度
C. 压缩纹理
D. 控制后处理
答案:A、B、C、D
解析:移动端常受带宽、发热和填充率限制。
15. UI/2D 渲染可能影响性能的因素有?
A. 大面积透明叠层
B. 频繁 Canvas rebuild
C. 图集拆分
D. Raycast Target 过多
答案:A、B、C、D
解析:UI 既有 CPU 重建成本,也有 GPU overdraw 成本。
16. GPU Instancing 适合哪些条件?
A. 大量相同 mesh
B. 相同材质/shader
C. 少量 per-instance 参数
D. 每个对象完全不同 shader
答案:A、B、C
解析:实例化依赖可共享的网格和材质状态。
17. LOD 的目的包括?
A. 远距离使用低细节模型
B. 降低顶点/三角形成本
C. 降低过远对象渲染压力
D. 保证所有距离都用最高模
答案:A、B、C
解析:LOD 用视觉可接受的方式换性能。
18. Culling 常见类型包括?
A. 视锥剔除
B. 遮挡剔除
C. 背面剔除
D. 距离剔除
答案:A、B、C、D
解析:剔除的目标都是减少无效绘制。
19. 法线贴图相关正确的有?
A. 通常存储扰动后的法线方向
B. 常配合 TBN 使用
C. 可增加光照细节
D. 会真实增加模型几何轮廓
答案:A、B、C
解析:法线贴图不改变真实几何轮廓。
20. 渲染问题定位常用工具有?
A. Frame Debugger
B. RenderDoc
C. Unity Profiler GPU/Rendering 模块
D. 抓帧分析
答案:A、B、C、D
解析:渲染问题通常要结合帧调试、GPU 计时和状态检查。
三、判断题
1. 顶点着色器通常按顶点执行。
答案:对
解析:它处理顶点属性并输出到后续阶段。
2. 片元着色器执行次数一定等于模型顶点数。
答案:错
解析:片元数量取决于光栅化覆盖。
3. MVP 中的 Projection 与投影变换有关。
答案:对
解析:它把观察空间映射到裁剪空间。
4. 深度测试可以帮助处理不透明物体遮挡关系。
答案:对
解析:深度缓冲用于比较片元远近。
5. 透明 alpha blending 的结果通常与绘制顺序无关。
答案:错
解析:常规 alpha 混合顺序相关。
6. DrawCall 越多,CPU 提交渲染命令的压力通常越大。
答案:对
解析:每次提交都有状态和命令成本。
7. 使用图集可能减少材质/纹理切换。
答案:对
解析:多个小纹理合并到同一纹理有利于合批。
8. Overdraw 对移动端填充率和带宽没有影响。
答案:错
解析:overdraw 会造成重复片元处理。
9. Early-Z 在所有 shader 状态下都一定生效。
答案:错
解析:discard、透明、深度写入修改等可能影响 Early-Z。
10. 延迟渲染通常需要 G-Buffer。
答案:对
解析:G-Buffer 是延迟光照的基础。
11. MSAA 对几何边缘锯齿更有效。
答案:对
解析:它对边缘覆盖采样更有价值。
12. 法线贴图会真实改变模型轮廓。
答案:错
解析:它改变光照法线,不改变几何轮廓。
13. ShadowMap 需要从光源视角生成深度信息。
答案:对
解析:之后从相机视角做深度比较。
14. PBR 中 roughness 越高,高光通常越集中锐利。
答案:错
解析:roughness 越高,高光越宽更粗糙。
15. Frame Debugger 可以帮助逐步查看渲染事件。
答案:对
解析:它适合排查绘制顺序、材质、batch 和状态。
四、填空题
1. MVP 中 M、V、P 分别常表示 Model、View、______。
答案:Projection
解析:P 表示投影矩阵。
2. 裁剪空间坐标做透视除法时,通常除以齐次坐标的 ______ 分量。
答案:w
解析:除以 w 后得到 NDC。
3. Lambert 漫反射常用公式核心为 max(dot(N,L), ______)。
答案:0
解析:背光面不能得到负光照。
4. 常规 alpha 混合公式可写作 src * alpha + dst * (1 - ______)。
答案:alpha
解析:源颜色按 alpha 混到目标颜色。
5. ShadowMap 通常从 ______ 视角渲染深度图。
答案:光源
解析:光源视角深度用于判断是否在阴影中。
6. AABB 视锥剔除、遮挡剔除、背面剔除都属于减少无效 ______ 的方法。
答案:绘制
解析:剔除减少不必要渲染工作。
7. GPU Instancing 适合大量相同 Mesh 和相同 ______ 的对象。
答案:材质
解析:状态一致才能一起实例化提交。
8. 延迟渲染中保存法线、深度、材质等信息的缓冲通常称为 ______。
答案:G-Buffer
解析:G-Buffer 是延迟光照输入。
9. 切线空间法线贴图常使用 T、B、N 组成的 ______ 矩阵。
答案:TBN
解析:TBN 用于空间转换。
10. 远处纹理使用低分辨率层级以减少闪烁和带宽,这种层级叫 ______。
答案:Mipmap
解析:mipmap 是多级纹理。
五、代码阅读题(C++/HLSL)
1. 点乘判断光照强度
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
float dotNL = -0.25f;
float diffuse = max(dotNL, 0.0f);
cout << diffuse;
return 0;
}答案:0
解析:Lambert 漫反射不能为负,背光面用 0 截断。
2. alpha 混合结果
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
using namespace std;
int main()
{
float src = 1.0f;
float dst = 0.0f;
float alpha = 0.25f;
float outColor = src * alpha + dst * (1.0f - alpha);
cout << outColor;
return 0;
}答案:0.25
解析:源颜色按 alpha=0.25 混入黑色背景。
3. 深度测试 LESS
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
using namespace std;
bool DepthLess(float incoming, float current)
{
return incoming < current;
}
int main()
{
cout << DepthLess(0.6f, 0.4f);
return 0;
}答案:0
解析:LESS 测试下,新片元深度 0.6 比已有 0.4 更远,测试失败。
4. 三角形绕序符号
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
using namespace std;
int main()
{
float ax = 0, ay = 0;
float bx = 1, by = 0;
float cx = 0, cy = 1;
float cross = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
cout << (cross > 0);
return 0;
}答案:1
解析:二维叉积为正,说明这组三点在该坐标约定下为逆时针。
5. 连续材质批次数
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> material = {1, 1, 2, 2, 1};
int batches = 0;
int last = -1;
for (int m : material)
{
if (m != last)
{
++batches;
last = m;
}
}
cout << batches;
return 0;
}答案:3
解析:连续相同材质可看作同批,材质序列变化为 1、2、1,共 3 段。
6. 向量归一化长度
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
float x = 3.0f;
float y = 4.0f;
float len = sqrt(x * x + y * y);
x /= len;
y /= len;
cout << x << "," << y;
return 0;
}答案:0.6,0.8
解析:长度为 5,归一化后为 (3/5, 4/5)。
7. Gamma 近似转换
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
float linear = 0.25f;
float gamma = sqrt(linear);
cout << gamma;
return 0;
}答案:0.5
解析:这里用 sqrt 做近似演示,0.25 的平方根是 0.5。
8. HLSL 语义判断
阅读代码,写出输出或说明问题:
hlsl
struct VSOut
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
// pos 会被后续光栅化阶段作为裁剪/屏幕相关位置使用。答案:pos 使用 SV_POSITION,uv 使用 TEXCOORD0
解析:SV_POSITION 是位置系统语义,TEXCOORD0 常用于传递纹理坐标。
9. 透明深度写入风险
阅读代码,写出输出或说明问题:
hlsl
// 伪代码:
DrawTransparentObjectA_DepthWriteOn();
DrawTransparentObjectB_BehindA();
// B 在深度测试时可能被 A 写入的深度挡掉。答案:风险:后面的透明物体可能无法正确混合
解析:常规透明渲染通常关闭深度写入,并按后到前排序。
10. mipmap 层级尺寸
阅读代码,写出输出或说明问题:
cpp
#include <iostream>
using namespace std;
int main()
{
int w = 256;
int h = 128;
w /= 2;
h /= 2;
cout << w << "x" << h;
return 0;
}答案:128x64
解析:mipmap 下一层通常宽高各减半,直到 1。
六、代码填空题(C++/HLSL)
1. 补全 Lambert 漫反射
补全横线处代码:
hlsl
float Lambert(float3 normalDir, float3 lightDir)
{
normalDir = normalize(normalDir);
lightDir = normalize(lightDir);
return max(______, 0.0);
}答案:dot(normalDir, lightDir)
解析:Lambert 核心是法线和光照方向点乘。
2. 补全 HLSL 顶点输出位置语义
补全横线处代码:
hlsl
struct Varyings
{
float4 positionCS : ______;
float2 uv : TEXCOORD0;
};答案:SV_POSITION
解析:顶点输出裁剪空间位置常用 SV_POSITION。
3. 补全 alpha 混合公式
补全横线处代码:
hlsl
float3 AlphaBlend(float3 src, float3 dst, float alpha)
{
return src * alpha + dst * (______ - alpha);
}答案:1.0
解析:常规源 alpha 混合为 src*a + dst*(1-a)。
4. 补全 C++ 向量长度
补全横线处代码:
cpp
float Length(float x, float y, float z)
{
return sqrt(x * x + y * y + ______);
}答案:z * z
解析:三维向量长度是三个分量平方和再开方。
5. 补全按列向量常见 MVP 组合
补全横线处代码:
hlsl
// column-vector convention
float4 clipPos = mul(______, localPos);答案:MVP
解析:在题目给定约定下,把本地坐标乘 MVP 得到裁剪空间坐标。
七、简答题
1. 简述前向渲染和延迟渲染的区别。
参考答案:前向渲染通常在物体 pass 中直接计算光照,透明处理较直观,材质灵活,但光源多时成本可能增加。延迟渲染先把几何信息写入 G-Buffer,再统一做光照,适合大量动态光源,但 G-Buffer 带宽和显存压力大,透明、MSAA、移动端带宽是常见难点。

2. 简述 DrawCall 过多的原因和优化方式。
参考答案:DrawCall 过多通常来自材质/Shader/纹理/渲染状态频繁切换,以及大量小物体逐个提交。优化方式包括图集、合批、GPU Instancing、材质复用、减少 shader keyword 变体、静态对象合并、LOD 和剔除;优化时要用 Frame Debugger 或抓帧工具确认是否真的合批。

3. 简述透明物体为什么难渲染。
参考答案:常规 alpha blending 与绘制顺序有关,多个透明物体相互穿插时很难用单一对象排序得到完全正确结果。透明物体通常关闭深度写入,按后到前绘制,但会增加 overdraw。复杂场景可能使用 alpha test、预乘 alpha、深度预处理、OIT 或特效分层策略。
八、场景分析题
1. 场景:移动端战斗场景 FPS 下降,Profiler 显示 GPU 压力高,画面有大量半透明特效和 UI 叠层。请分析并给出优化方案。
参考答案:优先怀疑 overdraw、片元 shader 复杂度、纹理带宽和后处理。可以用 overdraw 视图或抓帧工具确认热点;减少大面积透明面片和重叠层级;降低粒子数量和屏幕覆盖面积;简化特效 shader,减少采样和动态分支;UI 动静分离、压缩图集、关闭无用 Raycast Target;按机型做画质分级,限制后处理和特效等级。

2. 场景:项目中 DrawCall 很高,但美术认为已经用了图集。你会如何排查?
参考答案:先用 Frame Debugger/RenderDoc 查看 draw event 是否被材质、shader keyword、渲染队列、贴图、Lightmap、阴影、Instancing 参数或 Canvas 拆分。确认图集是否真正被同一材质引用,是否有材质实例化,是否被不同 Mask/Stencil/Canvas/排序层打断。再决定是合并材质、统一 shader keyword、减少材质实例、拆分动静 Canvas、启用 GPU Instancing,还是调整渲染顺序。
