Unity 性能优化五:渲染模块压力

CPU压力

Batching

在GPU渲染前,CPU会把数据按batch发送给GPU,每发送一次,都是一个drawcall,GPU在渲染每个batch的时候,会切换渲染状态,这里的渲染状态指的是:影响对象在屏幕上的外观的渲染属性或材质,比如:材质球,贴如,颜色,渲染模式(透明、半透明)等

unity中的合批方式:

优先级:
SRP Batcher / Static Batching
GPU Instancing
Dynamic Batching

Draw Call Batching的使用条件
1. 支持Mesh Renderers、Trail Renderers、Line Renderers、Particle Systems
和Sprite Renderers,且只能批量处理相同类型的Renderer,不支持skin renderers

2. 需要使用相同的材质,因此在脚本中要使用Renderer.sharedMaterial而不是
Render.material,后者生成的是材质的副本,会打断合批
3. 使用MaterialPropertyBlock也会打断合批,不过它还是比使用多个材质要快
4. 透明物体的渲染严格按照先后顺序执行,合批很容易被打断
5. 尽量不要使用负的缩放值
 

StaticBatching:

static batching 的目的不是减少drawcall ,而是减少渲染状态的改变,因为在渲染之前,要设置该物体的各种渲染属性,如果是同一个批次,只设置一次就好了。

static batching 之所以不会减少drawcall,是因为静态合批的物体是可以被裁剪的,它只是合并了顶点数组,但是顶点索引还是单独的,这样就可以根据索引值来决定绘制哪些submesh,比如10个网格 static batch 成了一个网格,但是第5个网格没在视锥体内,则有2个drawcall,第1-4个submesh,第6-10个submesh,第5个是被裁剪了,虽然是2个drawcall,但是渲染状态只设置1次

如果不静态合批,虽然这10个mesh 的材质球、贴图都是一样的,也会分10个drawcall 去绘制,也就是10个batch ,要设置10次渲染状态。


细节补充:
1. 在编辑器中静态合批,Unity不会使用任何运行时的CPU资源来生成网格数据
2. 运行时进行静态合批会有一次较高的CPU峰值,可能会造/成一次卡顿
3. 完成静态合批后,对象成为一个整体,且为静态,无法修改Transform属性
4. 运行时可以对合批后的根对象staticBatchRoot进行Transfform属性的修改,
5. 不过运行时合批的对象需要开启Read/Write选项
 

手动网格合并

手动合并网格,和静态合批差不多,但是它不能裁剪submesh,如果视野中只有单个submesh,也会绘制整个mesh

Dynamic Batching

它在Unity中有两种类型,一种针对网格,一种针对动态生成的几何体,比如粒子系统

动态合批的目的是为了减少CPU的耗时,但是合批本身就消耗CPU,所以它里合批的条件比较严格

GPU Instance

原理:
Unity对于所有符合要求的对象,将其位置、缩放、uv偏移、lightmappindex等相关信息一次性存到Constant Buffer常量缓冲区中,当一个对象作为实例进入渲染流程时,会根据传入的Instance ID来从显存中取出对应的信息,用于后续的渲染阶段,不用每次都发送数据到GPU,以此实现优化的效

使用方法
1. 在材质的Inspector面板中勾选Enable Instancing的选项
2. 使用Graphics.DrawMeshInstanced或Graphics.DrawMeshInstancedirdirect 手动调用GPU instance

MaterialPropertyBlock

使用MaterialPropertyBlock设置随机颜色,不会打断合批,如果直接用material.setcolor 则会打断合批,因为那是一个单独的材质球,它和GPU Instance 最适配,和SRP Batcher最不适配

缺点:优先级比较低、提交一次drawcall 耗时比平常要多一点

优点:

  • 相比静态合批不会带来额外的内存压力
  • 相比动态合批没有严格的顶点限制
  • 与MaterialPropertyBlock很适配,不会打断合批

适用场景:
需要画大批相同Mesh的场景,如草海、树林之类的

SRP Batcher

对于使用相同的着色器变体的材质,也就是对shader合批,即使材质球不一致,只要shader一致,就可以,当项目切换到SRP管线后,通过UniformBuffer传递信息,开启SRP Batcher后,会预先生成Uniform Buffer,批量传递信息,SRP Batcher以Shader为单位进行合批,可以有效降SetPassCall(设置渲染状态)的数目,用于CPU性能优化
 

原理:

对于未开启SPR Batcher的渲染流程是:每一个物体的属性都会在GPU上存在一个CBuffer,这里面包括Gameobject 属性,比如transform,material 属性,比如材质,光照贴图等。当其中属性更新时,就要重新设置数据,每增加一个material ,就会设置一遍对应的cbuffer,耗费CPU

开启了之后,流程发生了变化,相同的shader,对于那些不同的属性,比如transform,会生成一个大的buffer,对于相同的属性,比如光照贴图等,每一个都生成一个小的permaterial,当有状态改变时,才会修改该buffer,如果只是修改了transform,只会通过偏移写入相同位置的数据。

而对于新增的material,它的shader没变,则合批就不会变

传统上,人们倾向于减少Draw Call的数量来优化CPU,Draw Call本身只是推入GPU命令缓冲区的一些字节,真正的CPU成本来自于DrawCall之前的许多设置,SRP Batcher不会减少DrawCall的数量,它只是降低了Draw Call之间的设置成本

渲染管线要求:
支持URP、HDRP、SRP,不支持Built-in管线
游戏对象要求:
必须包含一个Mesh或者Skinned Mesh,不能是粒子
不能使用MaterialPropertyBlock
Shader必须兼容SRP Batcher
 

优点:
节省UniformBuffer的写入操作,支持动态物体,支持的范围要比静态合批更广泛,同时内存上的代价会小很多,材质多的情况也适用

适用场景:
Shader重复率高,但是要控制Shader变体的数量
 

四种方法的对比

优先级:
SRP Batcher / Static Batching > GPU Instancing > Dynamic Batching
适用情况:
Static Batching+SRP Batcher:主城,副本建筑
SRP BatcherOnly:种类繁多的植被
GPU Instancing:种类单一的植被
Dynamic Batching:Ul,粒子,Sprite等

Culling

在GPU进行渲染之前,需要CPU传递渲染数据给GPU,因此需要先将一部分不需要进行渲染的对象进行剔除,也就是Culling。Unity引擎原生就支持了视椎体剔除,即将视域体范围外的对象进行剔除,这部分对象的数据就不用传给GPU进行处理。

在Unity中,所有的可视内容都继承自Renderer,比如MeshRenderfer、SpriteRenderer、LineRenderer、SkinnedMesh Renderer、TrailRenderer等在Unity进行渲染的过程中会它们进行筛选,自动执行视锥体剔限的操作

如果场景中激活的相机数量多,那么Cullling的总耗时也相应增高,即使没有用来显示物体,也会执行culling 耗时,函数体现在  Render 线程中的->Camera.Renderer 

CullingGroup

CullingGroup是Unity提供的一个API接口,它本身和Unity自己的Cu系统以及LOD是同一体系,相当于开放了一些Cull底层的功能供用户使用
Unity - Manual: CullingGroup API

Occlusion

基本介绍
摄像机在每一帧中执行剔除操作,这些操作会检查场景中的渲染器,并排除
(剔除)那些不需要绘制的渲染器
默认情况下,摄像机执行视锥体剔除

工作原理
在Unity Editor中生成有关场景的数据,然后在运行时使用该数据确定摄像机可以看到的内容,生成数据的过程称为烘焙.
在对遮挡剔除数据进行烘焙时,Unity将场景划分为多个单元,并生成描述单元内几何体以及相邻单元之间可见性的数据,然后,Unity尽可能合并单元,以减小生成的数据的大小,在运行时,Unity会将这些烘焙的数据加载到内存中,并且对于每个启用了Occlusion Culling属性的摄像机,将会对数据执行查询以确定该摄像机可以看到的内容

在CullSendEvents的子线程下方会出现CullQueryPortalVisibilitylJmbra函数
测试中该函数也会出现在工作线程中

使用建议

遮挡物:

  • 大的遮挡物具有良好的遮挡质量,比如山
  • 组合起来大的遮挡物并不合适,因为遮挡无法累计,如森林
  • 不要有太多的缝隙,如奶酪
  • 建模时要注意避免无意造成的缝隙
  • 尽量不要让相机能进入遮挡物内部,可通过碰撞实现

被遮挡物:

  • 可以将大部分都设置为被遮挡物,便于被剔除
  • 非常大的物体不适合作为被遮挡物,因为它总会被看到,如地形,可以考虑将其分割为多个部分




 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/14396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入学习java虚拟机||JVM内存结构五大模型

目录 程序计数器 栈 虚拟机栈 垃圾回收是否涉及栈内存? 栈内存分配越大越好吗? 方法内的局部变量是否线程安全? 栈内存溢出 本地方法栈 堆 方法区 先看内存图总览 程序计数器 定义:全称P r o g r a m C o u n t e r R e …

windows下配置vue开发环境

安装nodejs,配置npm 1.下载安装包:下载地址:https://nodejs.org/en/download 2.安装node:下载完成后进行安装,记住安装的文件夹。本人安装路径为 D:\Program Files\nodejs 3.配置环境变量: ①安装完成后…

基于传统检测算法hog+svm实现图像多分类

直接上效果图: 代码仓库和视频演示b站视频005期: 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 代码展示: 数据集在datasets文件夹下 运行01train.py即可训练 训练结束后会保存模型在本地 运行02pyqt.py会有一个可视化…

某信用中心之加速乐实战分析

某信用中心之加速乐实战分析 某信用中心之加速乐实战分析声明逆向目标逆向分析第一层cookie获取第二层cookie获取调试分析JS文件 模拟执行致谢 某信用中心之加速乐实战分析 声明 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理&#x…

QTday2信号和槽

点击登录按钮,关闭Widget登录窗口,打开QQList窗口 widget.cpp #include "widget.h"void my_setupUI(Widget *w);Widget::Widget(QWidget *parent): QWidget(parent) {my_setupUI(this); }Widget::~Widget() { }void Widget::login_slots() {//fixemit jump_signal(…

CAN学习笔记1:计算机网络

计算机网络 1 概述 计算机网络就是把多种形式的计算机用通信线路连接起来,并使其能够互相进行交换的系统。实际上,计算机网络包括了计算机、各种硬件、各种软件、组成网络的体系结构、网络传输介质和网络通信计数。因此,计算机网络是计算机…

SpringCloudAlibaba之Ribbon

Ribbon是nacos自带的负载均衡器,属于客户端的负载均衡 但是在Spring高级版本中让LoadBalancer替代了 本人用的是2.1.0的nacos,ribbon还没有被替换。 使用: 在配置类中:LoadBalanced BeanLoadBalancedpublic RestTemplate restT…

【点云处理教程】05-Python 中的点云分割

一、说明 这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好,我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中,我们看到了如何过滤点云以减少噪声或其密度。在本教程中,我们将应用一些聚…

Redis(五)—— Redis进阶部分

一、Redis配置文件详解 注意这是Redis服务本身的配置文件&#xff0c;相当于maven的settings.xml&#xff0c;而不是我们在springboot去配置Redis的那个application.yml。 核心部分include 引入其他redis配置文件&#xff0c;相当于spring的<import>bind 设置IP&#xf…

Elasticsearch:通过动态修剪实现更快的基数聚合

作者&#xff1a;Adrien Grand Elasticsearch 8.9 通过支持动态修剪&#xff08;dynamic pruning&#xff09;引入了基数聚合加速。 这种优化需要满足特定的条件才能生效&#xff0c;但一旦实现&#xff0c;通常会产生惊人的结果。 我们观察到&#xff0c;通过此更改&#xff0…

C语言指针应该这么学?

数组名的意义&#xff1a; 1. sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小。 2. &数组名&#xff0c;这里的数组名表示整个数组&#xff0c;取出的是整个数组的地址。 3. 除此之外所有的数组名都表示首元素的地址。 根据以上数…

C++代码格式化工具clang-format详细介绍

文章目录 clang-format思考代码风格指南生成您的配置运行 clang-format禁用一段代码的格式设置clang-format的设置预览 clang-format 我曾在许多编程团队工作过&#xff0c;这些团队名义上都有“编程风格指南”。该指南经常被写下来并放置在开发人员很少查看的地方。几乎在每种…

网络编程 IO多路复用 [select版] (TCP网络聊天室)

//head.h 头文件 //TcpGrpSer.c 服务器端 //TcpGrpUsr.c 客户端 select函数 功能&#xff1a;阻塞函数&#xff0c;让内核去监测集合中的文件描述符是否准备就绪&#xff0c;若准备就绪则解除阻塞。 原型&#xff1a; #include <sys/select.…

BUG:pm2启动verdaccio报错:Invalid or unexpected toke

输入命令&#xff1a; pm2 state verdaccio 问题描述&#xff1a; pm2 logs verdaccio报错翻译&#xff1a;数据格式错误 导致我呢提原因&#xff0c;没有找到运行文件&#xff0c; 发现问题&#xff1a;因为命令默认查找verdaccio是去系统盘查找。 解决方式 1&#xff1a;…

Java+bcprov库实现对称和非对称加密算法

BouncyCastle&#xff0c;即BC&#xff0c;其是一款开源的密码包&#xff0c;包含了大量的密码算法。 本篇主要演示BC库引入&#xff0c;对称加密算法AES、SM4和 非对称加密EC算法的简单实现&#xff0c;以下是实现过程。 一、将BC添加到JRE环境 前提&#xff1a;已安装JRE环…

C# Socket实际应用案例与属性详解

引言 Socket是一个在网络编程中非常常见和重要的概念&#xff0c;它提供了一种通信机制&#xff0c;使不同的计算机之间可以进行数据传输。本文将介绍C#中Socket的实际应用案例&#xff0c;并对Socket的常用属性进行详细解析。 文章目录 1. Socket的实际应用案例2. Socket的属…

SqlServer读写分离对等发布

SqlServer读写分离对等发布: 对等发布支持多主复制。发布服务器将事务流式传输到拓扑中的所有对等方。所有对等节点可以读取和写入更改,且所有更改将传播到拓扑中的所有节点。 注意点: 1.各服务器的数据库名字要保证一样。 2.发布名称必须保持一致。 3.各服务器必须都是…

【论文阅读】The Deep Learning Compiler: A Comprehensive Survey

论文来源&#xff1a;Li M , Liu Y , Liu X ,et al.The Deep Learning Compiler: A Comprehensive Survey[J]. 2020.DOI:10.1109/TPDS.2020.3030548. 这是一篇关于深度学习编译器的综述类文章。 什么是深度学习编译器 深度学习&#xff08;Deep Learning&#xff09;编译器将…

【Maven】让maven更高效,优化maven构建项目速度

打开idea的setting&#xff0c;找到maven&#xff0c;设置它多线程数&#xff0c;重启后即可&#xff01; 我这里是8&#xff0c;你们可以随便设置。 如下图&#xff1a;

Github git clone 和 git push 特别慢的解决办法

1.在本地上使用 SSH 命令无法git push 上传 github 项目 2.使用 git clone 下载项目特别慢总是加载不了 解决办法1 将 *** 的连接模式换成&#xff1a;D-i-r-e-c-t&#xff08;好像不太有用&#xff09; 后面再找找能不能再G-l-o-b-a-l 下解决该问题 解决办法 2 mac下直接设…