[转载]Unity用户手册-Mesh合批

本文详细介绍了Unity3D中的静态合批(StaticBatching)和动态合批(Dynamicbatching)技术,用于减少DrawCall,提升渲染效率。静态合批适用于静止且材质、纹理、Shader相同的物体,而动态合批则适用于小模型的动态合批。文章还提供了 CombineMeshes 方法的使用示例,帮助理解合批过程。

Mesh合批

把很多静止的模型,标记为Batching Static,原本需要把模型一个个送到GPU渲染,Unity会把相同材质相同纹理相同Shader的模型合批成一个大的模型,送到GPU进行渲染,这样就减少DrawCall。可以调用Mesh.CombineMeshes方法,创建CombineInstance[]数组,进行合批。

Static Batching

要求:必须使用相同的材质material,相同的纹理Texture,然后在编辑器里设置为static batching的。
特点:静态批是无法运动的。
所以一般制作流程上,对于场景这些静态的物体都采用静态批,美术会根据场景的规模,将相邻的一片物件的贴图合并到一张或几张1024或512的大图上,这样这些物件可以使用同一个material,就可以静态批在一起,大幅节省DrawCall。 静态批的时候Unity3d会在运行时生成一个合并的大模型,并且为这个模型指定一张共同的贴图,所以这个批在一起的数量是有限的,如果批在一起的定点数过多,它就会自动分成两个批,一个静态批的上限为65535,这是因为Unity默认使用16位Mesh Index Buffer。

Dynamic batching

Dynamic batching的原理也很简单,在进行场景绘制之前将所有的共享同一材质的模型的顶点信息变换到世界空间中,然后通过一次Draw call绘制多个模型,达到合批的目的。模型顶点变换的操作是由CPU完成的,所以这会带来一些CPU的性能消耗。并且计算的模型顶点数量不宜太多,否则CPU串行计算耗费的时间太长会造成场景渲染卡顿,所以Dynamic batching只能处理一些小模型。
要求如下:
  • 目前Unity限制能进行Dynamic batching的模型最高能有900个顶点属性。这里注意不是900个顶点,而是900个顶点属性。如果我们在Shader中使用了Vertex Position,Normal and single UV,那么能够进行Dynamic batching的模型最多只能够有300个顶点。如果我们在Shader中使用了Vertex Position、Normal、UV0、UV1 and Tangent那么顶点的数量就减少到180个。
  • 批在一起的所有的模型应用同样的缩放值
  • 使用相同的材质
  • 相同的一张lightmap
  • 不能使用多pass的shader
  • 不能接收阴影

DrawCall

DrawCall是CPU通过底层图像编程接口发出的渲染命令,GPU读取渲染命令执行渲染操作。

过多的DrawCall影响绘制的原因:

主要是每次绘制时,CPU通过底层图像编程接口发出渲染命令DrawCall,而每个DrawCall需要很多准备工作,检测渲染状态、提交渲染数据、提交渲染状态,而GPU本身可以很快处理完渲染任务。DrawCall过多,CPU负载过多,而GPU性能闲置。

渲染状态

渲染状态定义场景中的网格是怎样被渲染出来的。例如使用哪个顶点着色器、哪个片元着色器、光源属性、材质等。如果没有更改渲染状态,所有的网格将使用同一种渲染状态。

Mesh.CombineMeshes方法

  • 遍历当前对象和子对象的MeshFilter组件,创建CombineInstance[]数组。
  • 获取filter.sharedMesh赋值给combine[i].mesh。
  • obj.transform.worldToLocalMatrix * filter.transform.localToWorldMatrix得到当前对象和子对象在本地空间的矩阵,赋值给combine[i].transform。
  • 遍历子对象所有的MeshRenderer组件,获取render.sharedMaterial存储在一个List中,然后赋值给当前对象的MeshRenderer的sharedMaterials。
  • 调用mesh.CombineMeshes(combine),合并Mesh。
  • 同时,还可以调用Unwrapping.GenerateSecondaryUVSet(meshFilter.sharedMesh);合并第二套UV。
    
using System . Collections . Generic ; using UnityEditor ; using UnityEngine ; public class CombineMesh { private const string MESH_PATH = "Assets/GameData/" ; [ MenuItem ( "Examples/CombineMesh" ) ] static void Combine ( ) { GameObject obj = Selection . activeGameObject ; if ( obj . GetComponent < MeshRenderer > ( ) == null ) { obj . AddComponent < MeshRenderer > ( ) ; } if ( obj . GetComponent < MeshFilter > ( ) == null ) { obj . AddComponent < MeshFilter > ( ) ; } List < Material > material = new List < Material > ( ) ; Matrix4x4 matrix = obj . transform . worldToLocalMatrix ; MeshFilter [ ] filters = obj . GetComponentsInChildren < MeshFilter > ( ) ; int filterLength = filters . Length ; CombineInstance [ ] combine = new CombineInstance [ filterLength ] ; for ( int i = 0 ; i < filterLength ; i ++ ) { MeshFilter filter = filters [ i ] ; MeshRenderer render = filter . GetComponent < MeshRenderer > ( ) ; if ( render == null ) { continue ; } if ( render . sharedMaterial != null && ! material . Contains ( render . sharedMaterial ) ) { material . Add ( render . sharedMaterial ) ; } combine [ i ] . mesh = filter . sharedMesh ; //对坐标系施加变换的方法是 当前对象和子对象在世界空间中的矩阵 左乘 当前对象从世界空间转换为本地空间的变换矩阵 //得到当前对象和子对象在本地空间的矩阵。 combine [ i ] . transform = matrix * filter . transform . localToWorldMatrix ; render . enabled = false ; } MeshFilter meshFilter = obj . GetComponent < MeshFilter > ( ) ; Mesh mesh = new Mesh ( ) ; mesh . name = "Combine" ; //合并Mesh mesh . CombineMeshes ( combine ) ; meshFilter . sharedMesh = mesh ; //合并第二套UV Unwrapping . GenerateSecondaryUVSet ( meshFilter . sharedMesh ) ; MeshRenderer renderer = obj . GetComponent < MeshRenderer > ( ) ; renderer . sharedMaterials = material . ToArray ( ) ; renderer . enabled = true ; MeshCollider collider = new MeshCollider ( ) ; if ( collider != null ) { collider . sharedMesh = mesh ; } string tempPath = MESH_PATH + obj . name + "_mesh.asset" ; AssetDatabase . CreateAsset ( meshFilter . sharedMesh , tempPath ) ; PrefabUtility . DisconnectPrefabInstance ( obj ) ; } }
对坐标系施加变换的方法
矩阵变换,当前对象和子对象在世界空间中的矩阵 左乘 当前对象从世界空间转换为本地空间的变换矩阵,得到当前对象和子对象在本地空间的矩阵。
本文经作者同意,转自知乎@鹅厂程序小哥(https://www.zhihu.com/people/tencentboy),原文链接(https://zhuanlan.zhihu.com/p/339380697)
内容概要:本文介绍了ENVI Deep Learning V1.0的操作教程,重点讲解了如何利用ENVI软件进行深度学习模型的训练与应用,以实现遥感图像中特定目标(如集装箱)的自动提取。教程涵盖了从数据准备、标签图像创建、模型初始化与训练,到执行分类及结果优化的完整流程,并介绍了精度评价与通过ENVI Modeler实现一键化建模的方法。系统基于TensorFlow框架,采用ENVINet5(U-Net变体)架构,支持通过点、线、面ROI或分类图生成标签数据,适用于多/高光谱影像的单一类别特征提取。; 适人群:具备遥感图像处理基础,熟悉ENVI软件操作,从事地理信息、测绘、环境监测等相关领域的技术人员或研究人员,尤其是希望将深度学习技术应用于遥感目标识别的初学者与实践者。; 使用场景及目标:①在遥感影像中自动识别和提取特定地物目标(如车辆、建筑、道路、集装箱等);②掌握ENVI环境下深度学习模型的训练流程与关键参数设置(如Patch Size、Epochs、Class Weight等);③通过模型调优与结果反馈提升分类精度,实现高效自动化信息提取。; 阅读建议:建议结实际遥感项目边学边练,重点关注标签数据制作、模型参数配置与结果后处理环节,充分利用ENVI Modeler进行自动化建模与参数优化,同时注意软硬件环境(特别是NVIDIA GPU)的配置要求以保障训练效率。
内容概要:本文系统阐述了企业新闻发稿在生成式引擎优化(GEO)时代下的全渠道策略与效果评估体系,涵盖当前企业传播面临的预算、资源、内容与效果评估四大挑战,并深入分析2025年新闻发稿行业五大趋势,包括AI驱动的智能化转型、精准化传播、首发内容价值提升、内容资产化及数据可视化。文章重点解析央媒、地方官媒、综门户和自媒体四类媒体资源的特性、传播优势与发稿策略,提出基于内容适配性、时间节奏、话题设计的策略制定方法,并构建涵盖品牌价值、销售转化与GEO优化的多维评估框架。此外,结“传声港”工具实操指南,提供AI智能投放、效果监测、自媒体管理与舆情应对的全流程解决方案,并针对科技、消费、B2B、区域品牌四大行业推出定制化发稿方案。; 适人群:企业市场/公关负责人、品牌传播管理者、数字营销从业者及中小企业决策者,具备一定媒体传播经验并希望提升发稿效率与ROI的专业人士。; 使用场景及目标:①制定科学的新闻发稿策略,实现从“流量思维”向“价值思维”转型;②构建央媒定调、门户扩散、自媒体互动的立体化传播矩阵;③利用AI工具实现精准投放与GEO优化,提升品牌在AI搜索中的权威性与可见性;④通过数据驱动评估体系量化品牌影响力与销售转化效果。; 阅读建议:建议结文中提供的实操清单、案例分析与工具指南进行系统学习,重点关注媒体适配性策略与GEO评估指标,在实际发稿中分阶段试点“AI+全渠道”组策略,并定期复盘优化,以实现品牌传播的长期复利效应。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值