90.性能优化-GPU-着色器优化-降低填充率压力-优化思路
90.1 知识点
知识回顾:填充率的优化思路
降低填充率压力的思路可归纳为三类:
降低要处理的像素(片元)数量
- 降低分辨率:动态分辨率(GPU 压力大时降低渲染分辨率再放大,目标稳定帧率,URP 有开关);注视点渲染(中央高分辨率、边缘低分辨率,多用于 VR);或基于目标设备合理设定项目分辨率。
- 减少或优化后处理:在 1/2 或 1/4 分辨率下渲染,或直接不用。
- 抗锯齿:4×MSAA → 2× 或关闭。
减少单个像素(片元)计算量
- 控制 Shader Pass 数量,能合并的效果放在一个 Pass。
- 减少半透明层数,必要时用透明测试(Alpha Test)。
- 合理使用光照模式,少用逐像素实时光照。
- 减少纹理采样(合并贴图、Mipmap)。
避免无效像素(片元)计算
- 减少 OverDraw。
- 优化 UI:减少叠层,避免全屏大半透明面板,合并图集减少 DrawCall。
- 剔除不可见对象:Occlusion Culling、视锥剔除。
禁用不需要的特性
降低填充率的核心是:减少被着色的像素数,以及减少每个像素的着色成本。透明度、深度写入、透明度测试、透明度混合等都会增加每像素的计算与逻辑,少一个特性就少一段像素级逻辑,能有效降低片元着色器工作量。
可通过渲染标签、渲染状态关闭不需要的处理,例如:
- 不投射阴影:
Tags { "ForceNoShadowCasting" = "True" } - 不写入深度:
ZWrite Off
按需禁用,避免多余开销。
使用基于着色器的 LOD
让 Unity 对远处物体使用更简单的 Shader,是节省填充率的有效手段,尤其适合多平台或多种硬件档位。
Shader LOD 为 Shader 提供多档复杂度(多个 SubShader 设不同 LOD),引擎根据全局或单 Shader 的 maximumLOD 选择对应档位,从而在远处减少片元计算、降低填充率压力。
Shader 示例:
Shader "Custom/LODExample"
{
// LOD 越高,引擎在允许时优先选用;远处或低档设备会选低 LOD 的 SubShader
SubShader {
LOD 300
Pass { /* 高级效果:法线贴图、PBR 等 */ }
}
SubShader {
LOD 150
Pass { /* 中级:Diffuse + 简单光照 */ }
}
SubShader {
LOD 50
Pass { /* 最低:纯颜色/贴图,片元计算最少 */ }
}
}
C# 中设置 LOD:
- 全局:
Shader.globalMaximumLOD = 200; - 仅对某 Shader:
Shader.Find("着色器路径").maximumLOD = 150;
使用光照剔除
光照计算在着色器里是典型的高开销项。灯光组件上的 Culling Mask(内置管线)或 Rendering Layer Mask(SRP)用于决定哪些层级的对象受该光源影响。通过合理设置,让不需要的层不受该光源照射,可限制光照计算范围,减少着色器中的光照相关计算。

谨慎使用实时阴影
实时阴影代价高:需要渲染阴影贴图,片元阶段还要采样、过滤等。尽量少用实时阴影,可减轻渲染与采样压力。替代与优化方式包括:使用烘焙光照阴影、降低阴影分辨率或质量档位。
使用烘焙的光照纹理
实时光照每像素计算量大。用烘焙结果可显著减少每像素的实时光照计算与采样:静态物体用光照烘焙贴图,动态物体用 Light Probe、Reflection Probe 等。思路是把实时计算改为预计算,运行时从纹理中取结果参与渲染。
减少多重渲染目标 (MRT)
多重渲染目标(MRT, Multiple Render Targets) 指一次绘制同时输出到多张 Render Target(如 G-Buffer 的 Albedo、Normal、Specular 等)。常用于延迟渲染的几何 Pass 或需要同时输出多张图的自定义特效。
MRT 的代价包括:每像素写入次数成倍增加(填充率压力大)、多张全屏级 RT 增加显存与带宽,在移动端 ROP 有限时尤其容易成为瓶颈。因此能不用 MRT 就不用;若必须使用,可通过纹理合并、压缩、降低精度、避免无效输出来优化。移动平台对 MRT 支持有限,需谨慎使用。
90.2 知识点代码
Lesson90_性能优化_GPU_着色器优化_降低填充率压力_优化思路.cs
public class Lesson90_性能优化_GPU_着色器优化_降低填充率压力_优化思路
{
#region 知识回顾 关于填充率的优化思路
// 1. 降低要处理的像素数量:动态分辨率、注视点渲染、降低项目分辨率;
// 后处理在低分辨率渲染或不用;降低 MSAA 或关闭。
// 2. 减少单像素计算量:控制 Pass 数量、减少半透明、合理光照模式、减少纹理采样。
// 3. 避免无效计算:减少 OverDraw、优化 UI 叠层与图集、Occlusion Culling 与视锥剔除。
#endregion
#region 知识点一 禁用不需要的特性
// 通过渲染标签、渲染状态关闭不需要的特性,减少每像素逻辑。
// 例如:ForceNoShadowCasting、ZWrite Off 等。
#endregion
#region 知识点二 使用基于着色器的 LOD
// Shader 多档 LOD,引擎按 maximumLOD 选档,远处用简单 SubShader 以降低填充率。
// 全局:Shader.globalMaximumLOD = 200;
// 单 Shader:Shader.Find("路径").maximumLOD = 150;
#endregion
#region 知识点三 使用光照剔除
// 灯光上的 Culling Mask(内置)或 Rendering Layer Mask(SRP)限制受光层级,
// 减少着色器中的光照计算范围。
#endregion
#region 知识点四 谨慎使用实时阴影
// 实时阴影需渲染阴影贴图与片元采样过滤,开销大。
// 优先烘焙阴影或降低阴影质量。
#endregion
#region 知识点五 使用烘焙的光照纹理
// 静态物体用光照烘焙贴图,动态物体用 Light Probe、Reflection Probe 等,
// 用预计算结果替代实时光照计算与采样。
#endregion
#region 知识点六 减少多重渲染目标 (MRT)
// MRT 一次绘制写多张 RT,填充率与显存、带宽压力大,移动端尤其需谨慎。
// 能不用则不用;必要时通过合并、压缩、降精度等方式优化。
#endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com