UnityShader入门精要——Unity中的渲染优化技术(二)

article/2025/7/19 13:03:48

减少DrawCall数目

 

最常见的优化技术——批处理。实现原理为减少渲染每一帧所需的drawcall数目。使用同一个材质的物体可以一起处理。

优点缺点
动态批处理切处理都是Unity 自动完成的,不需要我们自己做任何操作,而且物体是可以移动的限制很多,可能一-不小心就会破坏了这种机制,导致Unity无法动态批处理一些使用了相同材质的物体
静态批处理自由度很高,限制很少可能会占用更多的内存,而且经过静态批处理后的所有物体都不可以再移动

1 动态批处理

如果场景中有一些模型共享了同一个材质并满足一些条件,Unity就可以自动把它们进行批处理,从而只需要花费一个draw call就可以渲染所有的模型。动态批处理的基本原理是,每一帧把可以进行批处理的模型网格进行合并,再把合并后模型数据传递给GPU,然后使用同一个材质对其渲染。除了实现方便,动态批处理的另一个好处是,经过批处理的物体仍然可以移动,这是由于在处理每帧时Unity都会重新合并一次网格。

条件限制:

  • 能够进行动态批处理的网格的顶点属性规模要小于900。
  • 一般来说,所有对象都需要使用同一个缩放尺度,但在Unity5中,这种对模型缩放的限制已经不存在了。
  • 使用光照纹理(lightmap)的物体需要小心处理。因此,为了让这些物体可以被动态批处理,我们需要保证它们指向光照纹理中的同一个位置。
  • 多Pass的shader会中断批处理。

要渲染这样一个包含了4个物体的场景共需要两个批处理。其中,一个批处理用于绘制经过动态批处理合并后的3个立方体网格,另一个批处理用于绘制球体。我们可以从Save by batching看出批处理帮我们节省了两个draw call。

现在,我们再向场景中添加一个点光源,并调整它的位置使它可以照亮场景中的4个物体。由于场景中的物体都使用了多个Pass的shader,因此,点光源会对它们产生光照影响。

渲染一帧所需的批处理数目增大到了8,而Save by batching的数目也变成了0。这是因为,使用了多个Pass的shader在需要应用多个光照的情况下,破坏了动态批处理的机制,导致Unity不能对这些物体进行动态批处理。而由于平行光和点光源需要对4个物体分别产生影响,因此,需要2x4个批处理操作。需要注意的是,只有物体在点光源的影响范围内,Unity 才会调用额外的Pass来处理它。因此,如果场景中点光源距离物体很远,那么它们仍然会被动态批处理的。

 

2 静态批处理 

Unity提供了另一种批处理方式,即静态批处理。相比于动态批处理来说,静态批处理适用于任何大小的几何模型。它的实现原理是,只在运行开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中,这意味着这些模型不可以在运行时刻被移动。但由于它只需要进行一次合并操作,因此,比动态批处理更加高效。

尽管3个Teapot模型使用了相同的材质,但它们仍然没有被动态批处理。这是因为,Teapot 模型包含的顶点数目是393,而它们使用的shader 中需要使用4个顶点属性(顶点位置、法线方向、切线方向和纹理坐标),超过了动态批处理中限定的900限制。此时,要想减少drawcall就需要使用静态批处理。

静态批处理的实现非常简单,只需要把物体面板上的Static复选框勾选上即可。

现在的批处理数目变成了2,而Save by batching数目也显示为2。此时,如果我们在运行时查看每个模型使用的网格,会发现它们都变成了一一个名为Combined Mesh (roo:scene)的东西。这个网格是Unity 合并了所有被标识为“Static" 的物体的结果,在我们的例子里,就是3个Teapot和一个立方体。这个合并后的网格其实包含了4个子网格,即场景中的4个对象。对于合并后的网格,Unity 会判断其中使用同一个材质的子网格,然后对它们进行批处理。

 如果场景中包含了除了平行光以外的其他光源,并且在shader中定义了额外的Pass来处理它们,这些额外的Pass部分是不会被批处理的。但是,处理平行光的Base Pass部分仍然会被静态批处理,因此,我们仍然可以节省两个draw call。

3 共享材质

无论是动态批处理还是静态批处理,都要求模型之间需要共享同一个材质。但不同的模型之间总会需要有不同的渲染属性,如果两个材质之间只有使用的纹理不同,我们可以把这些纹理合并到一张更大的纹理中,这张更大的纹理被称为是一张图集(atlas)。 一旦使用了同一张纹理,我们就可以使用同一个材质,再使用不同的采样坐标对纹理采样即可。

如果调整微小的参数,如颜色,浮点属性等,一种常用的方法就是使用网格的顶点数据(最常见的就是顶点颜色数据)来存储这些参数。

需要注意的是,如果我们需要在脚本中访问共享材质,应该使用Renderer.sharedMaterial来保证修改的是和其他物体共享的材质,但这意味着修改会应用到所有使用该材质的物体上。另一个类似的API是Renderer.material,如果使用Renderer.material 来修改材质,Unity会创建一个该材质的复制品,从而破坏批处理在该物体上的应用,这可能并不是我们希望看到的。

4 注意事项

  1. 尽可能选择静态批处理,但得时刻小心对内存的消耗,并且记住经过静态批处理的物体不可以再被移动。
  2. 如果无法进行静态批处理,而要使用动态批处理的话,那么请小心上面提到的各种条件限制。例如,尽可能让这样的物体少并且尽可能让这些物体包含少量的顶点属性和顶点数目。
  3. 对于游戏中的小道具,例如可以捡拾的金币等,可以使用动态批处理。
  4. 对于包含动画的这类物体,我们无法全部使用静态批处理,但其中如果有不动的部分,可
    以把这部分标识成“Static"。

由于批处理需要把多个模型变换到世界空间下再合并它们,因此,如果shader中存在一些基于模型空间下的坐标的运算,那么往往会得到错误的结果。

一个解决方法是,在shader中使用DisableBatching标签来强制使用该Shader的材质不会被批处理。

另一个注意事项是,使用半透明材质的物体通常需要使用严格的从后往前的绘制顺序来保证透明混合的正确性。对于这些物体,Unity 会首先保证它们的绘制顺序,再尝试对它们进行批处理。这意味着,当绘制顺序无法满足时,批处理无法在这些物体上被成功应用。


http://chatgpt.dhexx.cn/article/A2IOAgOh.shtml

相关文章

Unity渲染顺序(2)

Camera 除了Screen Space - Overlay(屏幕空间覆盖模式)下的Canvas,场景中的其他物体需要渲染到屏幕中,都需要在指定的相机的绘制下。场景中可以创建多个相机,每个相机所拍摄的内容可能并不相同,在场景中有多相机的情况,不同的相机…

Unity渲染顺序(1)

添加排序层级 在Unity编辑器的右上角选择Layers 按钮,在下拉菜单中点击Edit Layers…选项,将显示当前Unity的Tags, Sorting Layers,和Layers 编辑选项。 Sorting Layers是Unity中对排序的层级的定义块,在面板中越靠后的排序层级越…

Unity的渲染流程

Unity中坐标空间的转换: Unity的渲染流程: 渲染到设备屏幕的每一帧画面都要经历如下几个阶段: 应用程序阶段(CPU):将材质和模型数据发送给GPU 几何阶段(GPU):进行顶点…

Unity 渲染原理

1 渲染流程 应用程序阶段(CPU):识别出潜在可视的网格实例,并把他们及其材质提交给 GPU 以供渲染。几何阶段(GPU):进行顶点变换等计算,并将三角形转换到齐次空间并进行裁剪。光栅化阶…

Unity标准化的场景渲染流程

笔者用的unity版本为2020.3.30f1c1,开一个HDRP模板场景,OK开始我们的操作。 第一步:删除场景中的所有东西只留下竹林玻璃房作为展示场景,将所有物体勾选Static,新增一个摄像机,如下图: 第二步&a…

Unity3D性能优化——渲染篇

大渣好,我又来了。 之前的文章中,我们了解了Profiler工具,以及在实际项目中unity的CPU优化分析及方法,本文我们主要了解在我们的项目中GPU的性能分析,以及对GPU性能进行优化的相关技术。 渲染优化 在了解优化渲染前&a…

Unity中的灯光和渲染

一:Unity中的灯光 ——Directional Light:模拟太阳光。它与位置无关,是平行光,可以调整旋转角度模拟昼夜 ——Spot Light:模拟车灯、手电筒的光、舞台灯光 ——Point Light:模拟灯泡 ——Area Light&#…

execv 函数的应用

execv函数族:系统来调用某程序模块 int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char * const envp[]); int ex…

Linux 0.11-execve函数-35

Linux 0.11-execve函数-35 execve函数读取文件开头 1KB 的数据解析这 1KB 的数据为 exec 结构判断是脚本文件还是可执行文件准备参数空间设置 eip 和 esp,完成摇身一变累了吧,休息会 转载 execve函数 书接上回,上回书咱们说到,进…

Linux内核Hook系统调用execve

资源下载地址:linux内核hook系统调用execve函数-Linux文档类资源-CSDN下载 (已在内核为 4.19.0-amd64-desktop版本uos编译通过,并成功达到目的) 在Linux系统中,用户层程序无法直接控制系统内核,只能通过系…

执行新程序 execve()

新程序的执行 一:execve() 之所以叫新程序的执行,原因是这部分内容一般发生在fork()和vfork()之后,在子进程中通过系统调用execve()可以将新程序加载到子进程的内存空间。这个操作会丢弃原来的子进程execve()之后的部分,而子进程…

简单的execve流程

本文转载于网络 基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取 _sys_execve:lea EIP(%esp),%eax #取堆栈中存放系统调用的返回地址的地址pushl %eax #将该地址入栈call _do_execve #调用do_execve函数addl $4,%esp #丢弃该地址ret这边做了一个很…

Linux0.11系统调用之execve流程解析

Linux0.11系统调用之execve流程解析 前言execve功能介绍execve本质execve系统调用流程总结 前言 本文是基于Linux0.11源码来叙述该功能,源码可以在oldlinux.org上自行获取。 execve功能介绍 execve是用于运行用户程序(a.out)或shell脚本的…

5.execve()到底干了啥?

导语 很多童鞋有分析阅读Linux源代码的强烈愿望,可是Linux内核代码量庞大,大部分人不知道如何下手,以下是我分析Linux源代码的一些经验,仅供参考,有不实之处请大神指正! 1.要想阅读内核首先要进入内核&…

Linux系统编程(再论execve)

文章目录 前言一、execve的第三个参数二、进程空间三、命令行参数规范四、optstring规则的扩展定义总结 前言 本篇文章我们继续来研究一下execve这个系统调用,上篇文章已经讲解了前两个参数的意义了,那么这篇文章就来讲解一下第三个参数的具体含义。 一…

Linux0.11 execve函数(六)

系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件打开open函数(五&#xff09…

C语言 execve()函数使用方法

1.君の名は execve() – 叫做执行程序函数 就像Python中的os.system(cmd)这个函数,我们可以用这个函数来执行我们的shell脚本,单独的shell命令,或者是调用其他的程序,我们的execve()这个函数就和Python中的os.system函数类似&am…

SPSS-因子分析

因子分析 有可能用较少的综合指标分析存在于各变量中的各类信息,而各综合指标之间彼此是不相关的,代表各类信息的综合指标称为因子。定义:因子分析就是用少数几个因子来描述许多指标或因素之间的联系,以较少几个因子反映原资料的 …

spss进行主成分分析

什么是主成分分析 简而概之, 就是一组数据受太多因素影响, 选出几个能代表他们的因素,并进行线性组合得到一组比原维度小的因素组合, 作为新的因素集 用spss操作 随手拿出一组数据 1.数据统一标准化 因为我们得到的原始数据大小,类型不一, 一起分析会不准确, 所以将数据全部…

实用干货!因子分析超全步骤总结

因子分析是统计数据分析方法之一,因子分析包括探索性因子分析和验证性因子分析。本文主要讨论探索性因子分析。 一、研究背景 关于工作满意度有14个问题,调研得到215份问卷结果。希望通过因子分析,用少量因子反映14个题目的信息,…