90.降低着色器填充率压力优化思路

90.性能优化-GPU-着色器优化-降低填充率压力-优化思路


90.1 知识点

知识回顾:填充率的优化思路

降低填充率压力的思路可归纳为三类:

  1. 降低要处理的像素(片元)数量

    • 降低分辨率:动态分辨率(GPU 压力大时降低渲染分辨率再放大,目标稳定帧率,URP 有开关);注视点渲染(中央高分辨率、边缘低分辨率,多用于 VR);或基于目标设备合理设定项目分辨率。
    • 减少或优化后处理:在 1/2 或 1/4 分辨率下渲染,或直接不用。
    • 抗锯齿:4×MSAA → 2× 或关闭。
  2. 减少单个像素(片元)计算量

    • 控制 Shader Pass 数量,能合并的效果放在一个 Pass。
    • 减少半透明层数,必要时用透明测试(Alpha Test)。
    • 合理使用光照模式,少用逐像素实时光照。
    • 减少纹理采样(合并贴图、Mipmap)。
  3. 避免无效像素(片元)计算

    • 减少 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

×

喜欢就点赞,疼爱就打赏