UPL9-15——反射探针
UPL9-15——反射探针 前置知识: US3S8L1——立方体纹理 US3S8L2——天空盒 US3S8L3——动态生成立方体纹理 US3S8L4——反射效果 反射探针 反射探针(Reflection Probe)是用来捕捉某个空间内的环境反射信息的组件,Unity 通过在场景中放置一个 立方体探针(Cube Probe) 拍摄周围环境生成一个 立方体贴图(Cubemap),运行时动态物体或表面就能从中采样反射 说人话:反射探针用一张立方体贴图来模拟物体周围的反射环境,让金属、玻璃等材质看起来有倒影感 反射探针(Reflection Probe)的原理 烘焙阶段 Unity 以探针位置为中心渲染场景的 6 个方向(±X, ±Y, ±Z)生成一张 6 面的立方体贴图(Cubemap) 这张贴图包含该点周围环境的颜色和亮度信息 运行阶段 对于反射性材质(如金属),Shader 在像素着色时,根据该像素的法线方向 在 Cubemap 中查找对应方向的颜色,将结果作为反射光加入最终颜色 混合 若一个物体位于多个反射探针之间,Unity...
UPL9-14——光照探针
UPL9-14——光照探针 光照探针 上一篇提到的光照烘焙,主要是为静态物体服务的,静态物体的光照信息直接烘焙进了光照贴图中 而动态物体由于自身会不停移动,受光影响的结果是不能直接烘焙进贴图的,所以烘焙光照无法作用于动态物体上 如果需要让动态物体收到直接光照,可以将光源改为 Mixed 模式,不过动态物体依然不能受到间接光的影响 而光照探针(Light Probe)可以用于解决 烘焙光源产生的间接光不能作用于动态物体 的问题,它让动态物体在场景中通过插值获得周围环境的间接光信息 间接光照(Indirect Lighting)是由光线在场景中经过一次或多次反射后,再照射到物体表面的光照 举例: 灯直接照在桌面上为 直接光照 桌面反射的光线照亮了墙壁、天花板为 间接光照 墙壁又反射出微弱的光照亮房间阴暗处为...
UPL9-13——光照烘焙
UPL9-13——光照烘焙 光照烘焙 提前离线计算场景中的光照、阴影、反射、间接光照等信息,并且将结果保存为贴图或探针数据 在游戏运行时直接使用,从而节省实时计算的性能消耗 为什么可以节约性能 实时光照:运行时每帧都需要计算,开销很大 烘焙光照:提前计算,运行时直接贴图,几乎零性能开销(因为不用实时计算光照) 说人话: 提前把光照表现算好存储到光照纹理中,运行时直接使用光照纹理中的颜色用于着色 避免实时计算带来的高开销,是典型的 内存换性能 的优化方式 哪些光照信息可以被烘焙 可以被烘焙的光照信息: 直接光照 来自光源直接照射到表面的光 间接光照 光线在场景中多次反射后的柔和照明 阴影 可烘焙静态阴影(不会随动态物体移动) 反射 可通过 反射探针(Reflection Probe) 烘焙环境反射 不可被烘焙的光照信息:不支持随时间变化的灯光(包括位置方向和光照强度) 或 移动的光源 如何进行光照烘焙 将场景中想要进行光照烘焙的静态物体标记为静态 Static,或 只勾选 Contribute GI(Contribute Global...
UPL9-12——阴影质量
UPL9-12——阴影质量 前置知识: US3S6L1——阴影的基本原理 US3S6L2——Unity中阴影的实现原理 内置渲染管线设置阴影质量 工程设置中的质量设置 相关设置在 Project Setting —— Quality —— Shadows 中: Shadowmask Mode:遮罩模式 Shadowmask(阴影遮罩) 静态物体的阴影都来自光照贴图,动态物体投射的阴影混合在 Shadowmask 里 Distance Shadowmask(距离阴影遮罩) 近处用实时阴影,远处用光照贴图里的 Shadowmask,平衡性能和质量 移动端建议选择 Distance Shadowmask Shadows:阴影 Disable Shadows(全局禁用阴影) 即使光源(Light)里设置了投射阴影,物体也不会产生阴影 Hard Shadows Only(仅开启硬阴影) 开启 硬阴影(边缘清晰锐利) 性能消耗相对低,阴影看起来不自然,尤其是远处或柔光场景 适用于移动端、低端设备或风格化游戏 Hard and Soft...
UPL9-11——降低 Shader 填充率压力
UPL9-11——降低 Shader 填充率压力 回顾:关于填充率的优化思路 具体可见:UPL8——影响 GPU 性能的主要因素 的 填充率部分 降低要处理的像素(片元)数量 降低分辨率 动态分辨率(Dynamic Resolution Scaling) 基本原理: 在 GPU 压力大时,降低渲染分辨率,然后再放大到屏幕分辨率输出 在 GPU 空闲时,提高渲染分辨率,获得更清晰的画面 目标是保持 稳定帧率,URP 项目中有动态分辨率功能开关 注视点渲染(Foveated Rendering) 基本原理: 人眼的视觉分辨率,中央注视点区域最清晰,周边区域分辨率敏感度低 在中央区域渲染高分辨率,在边缘区域渲染低分辨率,从而减少像素处理量 一般 VR 项目中会使用 一般 VR 设备会提供对应功能,通过设备 API 开启 降低项目分辨率 基于目标设备,合理设定项目目标分辨率 减少或优化屏幕后处理效果的使用 在 1/2 或 1/4 分辨率下渲染,或直接不使用 降低抗锯齿采样次数或关闭 4×MSAA ——> 2×MSAA...
UPL9-10——减少 Shader 采样开销
UPL9-10——减少 Shader 采样开销 减少纹理采样 纹理采样是所有内存带宽开销的核心消耗 使用的纹理越少、分辨率越合适,缓存命中率更高,带宽占用更低,性能更好 使用的纹理越多,则在调用过程中缓存丢失的情况就越多 制作的纹理越大,将它们传输到纹理缓冲消耗的内存带宽就越多 因此我们应该尽量的杜绝这些情况的发生,避免产生 GPU 瓶颈 比如我们可以通过把多个纹理合并成一张纹理的方式, 有效的减少纹理采样:可以把 金属度、粗糙度、环境光遮蔽 三张黑白图 打包到一张 RGBA 纹理的 RGB 通道中 使用更少的纹理数据 每次采样传输的数据量越小,显存带宽和缓存压力就越小 我们可以通过降低分辨率、减少通道的方式,去掉用不到的高精度 比如我们可以用 R8 格式代替 RGBA32 格式 遮罩贴图只需要一个灰度通道,用 R8 格式即可 R8: 每个像素只存储一个通道(R 通道) 每个像素 8 位 = 1 字节 RGBA32: 每个像素存储四个通道(RGBA 通道) 每个像素 32 位 = 4 字节 测试不同 GPU 纹理压缩格式 Unity...
UPL9-9——降低 Shader 计算量
UPL9-9——降低 Shader 计算量 尽量使用针对移动平台的着色器 Unity 中内置了很多专门针对移动平台的 Shader,那么即使我们开发的是非移动平台项目也可以选择使用它 前提:使用这些 Shader 带来的效果损失项目是可以接受的 这样我们不需要修改任何 Shader 代码,直接改变使用的内置 Shader 就能带来明显性能提升 使用小的数据类型并且避免精度转换 在 GPU 里使用更小的数据类型来计算比使用更大的数据类型速度可能会更快(尤其是在移动端时) 因此我们可以更多的选择使用 half、fixed,尽量少用 float 类型 注意:桌面 GPU 中,half 常常会被当作 float 处理,性能提升有限 我们应该避免频繁的在低精度和高精度之间相互转换,尽量在同一 Shader 内保持一致的精度选择,因为精度转换会损耗性能 尽量使用GPU优化的辅助函数 Unity 中提供了很多内置 Shader...
UPL9-8——着色器优化
UPL9-8——着色器优化 前置知识:US——Unity Shader开发入门 着色器优化的必要性 在开发时,为了快捷的实现对应的渲染效果,一些 Shader 制作者(程序、美术、技美等)会使用 Shader 可视化编辑器生成 Shader 比如 Shader Graph、ASE(Amplify Shader Editor) 等,通过这些可视化编辑器生成的 Shader 的性能表现往往不是最优异的 主要原因: Shader Graph、ASE 等工具为了适配各种情况,会生成比较通用的着色器代码,里面可能包含一些 冗余计算 或 不必要的分支 节点式编辑为了可读性,往往拆分为很多中间步骤,编译后可能比手写 Shader 冗长 手写 Shader 可以在指令级别做微调,比如合并数学运算、避免精度浪费,而可视化工具的优化程度受限 因此学习着色器优化的必要性就体现了出来,不管是对这些可视化编辑器生成的 Shader,还是我们自己通过代码编写的 Shader 养成良好的优化习惯都是对项目有益处的,可以避免我们在Shader上浪费性能 总结下 必要的原因: Shader 其实是...
UPL9-7——优化粒子系统
UPL9-7——优化粒子系统 粒子系统为什么会带来性能消耗 CPU 消耗: 粒子系统中,大多数模块都是 CPU 驱动模拟的,每帧会做很多工作,比如: 粒子的生命周期管理、位置、速度、加速度、物理碰撞、回调函数调用、排序、包围盒更新、剔除、脚本交互 等等内容 这些内容需要 CPU 每帧计算,那么它自然会带来 CPU 消耗 若不同粒子之间的材质和网格不同,还会打断批处理,产生额外 DrawCall 如果不使用批处理方案,在 DrawCall 上也存在更多开销 GPU消耗: 粒子能被看到肯定需要渲染,那么当粒子被提交到 GPU 渲染时: 顶点阶段的计算、片元阶段的计算、纹理采样、透明混合、阴影、光照影响都会给 GPU 带来消耗 尤其是半透明粒子容易造成 OverDraw,会显著增加 GPU 负担 由于粒子系统的表现特殊性,往往需要依赖 大量粒子叠加 来表现复杂效果 如果不加控制,粒子数量增长会在 CPU、GPU 两方面同时放大开销 因此需要特别关注粒子系统的性能影响与优化 粒子系统主要优化思路 CPU 侧优化思路 CPU 侧:优化目标 ——...
UPL9-6——优化 UI 系统
UPL9-6——优化 UI 系统 使用更多 Canvas 组件 Canvas(画布)组件的基本工作原理 任何 UGUI 控件都必须挂在一个 Canvas 下,Unity 才会把它们作为 UI 元素渲染出来,Canvas 的本质作用: 收集子节点的 UI 元素(Graphic)信息 处理渲染顺序(Sorting、Camera、RenderMode) 管理重建,监听子物体的变动,决定哪些需要更新 批量生成 UI 顶点网格、更新材质信息 最终在渲染阶段合批并提交给 GPU 等等 Canvas 内部维护了一个重建队列,当子元素发生变化时,它会标记自己为 “脏”(dirty) 在本帧渲染前统一执行重建(布局重建 / 图形重建 / 材质重建) 布局重建:主要进行布局计算 图形重建:主要进行网格生成(比如合并 UI 元素网格信息、前提是材质相同) 材质重建:主要进行材质状态更新 所谓“画布污染”,就是有子元素打了脏标记,导致整个 Canvas 的顶点缓存需要刷新 如果 Canvas 很大,就会让大量 UI 元素一并重建,带来性能消耗 可能带来画布污染的情况: 修改 UI 元素的...
