找回密码
 立即注册
查看: 207|回复: 0

Unity3D游戏开发中一些常见的问题解答(四)

[复制链接]
发表于 2022-11-12 15:16 | 显示全部楼层 |阅读模式
前言

我们在游戏开发中,总会遇到一些问题。那么今天我们就一些常见的问题做出一下解答
对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀!
1.Unity 自定义Shader 与 内置Shader 如何整合比较好?
根据实际的需求,如果内置的Shader符合你的需求,就可以直接使用,如果不符合,可以自己来开发一些Shader, 内置的Shader可以作为很好的源码参考,为我们自定义Shader开发提供很多好的参考。同时内置的Shader是考虑通用情况,对于项目来说,我们可以结合特殊的情况来进行优化,还有很大的优化空间。有些内置的Shader达不到渲染效果,我们必需要重新编写Shader。有些不同平台,Shader的效果不一样,我们可能要抹平这些差异,需要编写Shader。不同的渲染管线,内置的shader是不一样的,所以要基于渲染管线来区分Shader。
2.编写Unity Shader的时候,语义POSITION和SV_POSITION的区别?
没有什么区别,就是要给容器而已,可以存放任意的数据和shader约定的数据。
比如顶点shader那顶点的坐标,就到POSITION这个盒子去拿, 可以把他们当作是一个个的盒子就可以了
3.Unity中DrawCall和openGL、光栅化等有何内在联系,为什么说DC降低有助于渲染性能优化?
游戏引擎绘制一个游戏画面,遍历游戏场景中所有要绘制的物体,然后把这些物体提交给GPU来进行绘制。假设游戏场景中有100个需要位置的物体,假设游戏引擎把这100个物体一个一个的提交给GPU来进行绘制,绘制物体的时候游戏引擎底层会做下面的事情:
a:CPU 传递物体的渲染所需要的数据给GPU, 如网格模型,材质里面的一些参数,纹理对象, 物体的位置旋转缩放对应的矩阵, 摄像机的投影变换矩阵等数据。
b:CPU 把数据准备好以后,接下来向GPU来下达绘制命令(Draw cmd) 。
c: GPU 开机来渲染CPU提交过来的物体到我们的显示目标上。
CPU传递数据到GPU,CPU向GPU下达绘制命令,GPU绘制物体到屏幕都会产生性能开销。
  在分析降低Drawcall为什么能提升渲染性能的原理之前先给大家介绍几个概念:
   a: Drawcall: CPU提交数据给GPU,然后向GPU下渲染命令这个过程我们通常叫做DrawCall, 又叫同一个批次渲染。
   b: Drawcall数目(批次数): 游戏引擎绘制完一个游戏场景中的所有物体需要向GPU提交几次渲染命令(Drawcall)。100个物体,一个个提交给GPU一个一个绘制,那么就要向GPU提交100次渲染命令(Drawcall)所以Drawcall数幕是100。又一种说话就是绘制一个游戏场景的物体分成了多少个批次来进行渲染的。
  c: 合批(降低Drawcall数目): 把几个物体合在一起提交给GPU渲染绘制叫做合批。通过合批,可以降低绘制游戏场景的Drawcall数目。比如100个物体,我把前50个物体合在一起提交给GPU渲染,后50个物体合一起提交给GPU渲染,那么渲染100个物体用通过2批渲染绘制完成,也就是2次Drawcall。合批其实就降低了Drawcall的数目,我们通常说的降低Drawcall指的就是合批。
摆好这几个概念以后,接下来我们来分析合批对渲染性能有哪些方面的提升,提升点如下:
   a:CPU把能合批的物体一起提交给GPU,避免重复的数据提交,如同一个模型的多个物体。CPU给GPU提交数据开销比较大。(大于CPU对内存的数据拷贝)
  b:100个物体一个一个物体的绘制就要下达100次Draw Cmd, 而把100个物体合成一批提交给GPU,只要下达一次Draw Cmd,也就是GPU只要“开机”一次就能把所有的渲染完成,GPU不用“开机”100次。
  c: 每个GPU每次“开机”绘制,都有一个吞吐量,如果我们尽可能的每次提交多提交一些三角形的面数,GPU一次渲染能吃更多的面,这样提升GPU的效率。就像工厂的流水线,只要开机,产100个商品和产1个商品的代价一样,那么在安排订单的时候,尽量每次开机凑够100个。所以合批提交渲染,能提升GPU的吞吐量,提升效率。
所以从上分析可以得出结论:尽可能的把物体合批到一起渲染(降低Drawcall数目)对于渲染优化是非常有效果的。
4.在Unity存在动态合批的情况下,对mesh合并是为了什么?
动态合批: 每次渲染之前,CPU将能够合批的物体的每个顶点的世界坐标计算出来(模型顶点坐标*世界变化矩阵),然后再把合批物体的顶点的世界坐标提交给GPU,然后世界矩阵用单位矩阵,来达到合批的效果。
动态合批的优点分析:
     a:能获得合批所带来的渲染性能的提升;
     b:适合移动的物体,因为每次渲染之前都会重新计算坐标;
     c:没有额外的内存开销;
动态合批的缺点分析:
     a:每次渲染物体,CPU都要计算一次模型坐标到世界坐标,所有增加了CPU的负担。使用动态合批的时候,要把CPU的额外的开销和合批带来的提升做一个权衡,所以动态合批不是万能的,不适合太多顶点数目的物体的渲染绘制。
从原理与缺点可以看出来,动态合批的开销,以及为什么要做mesh的静态合并了。
Mesh合并其实原理就是静态合批,我们再来看下静态合批的原理与优缺点,如下
静态合批: 将“能够合批”物体的所有的网格按照它的位置预先重新合并生成一个大的新网格对象存到内存, 由于这些物体满足合批条件,都是同一个材质球,这样渲染这些物体只要把合并后的这个新网格对象一次提交给GPU,那么就能够实现把这些物体合批处理,降低Drawcall。
静态合批的优点分析:
  a:能将一组渲染物体合批,获得合批所带来的渲染性能的提升
静态合批的缺点分析:
  a:静态合批需要预先计算合并网格,延迟了运行初始化时的时间;
  b:静态合批一但预先计算好合并后的网格,这些物体就不能再“移动”了除非每次重新计算合并网格(CPU也是开销),所以叫做静态合批。因为它不适合有经常移动的物体的合批。
  c: 静态物体网格合并后可能会增大内存开销。这个点很多人不理解,觉得100个物体的Mesh数据合并后还是100个物体的Mesh数据不应该增加内存开销的,怎么会合并后会“可能”增大内存开销呢?这里首先有“可能”两个字,也就是说某些情况下会增加,某些情况下不会增加。试想一下如果100个物体完全不一样,合并后的Mesh顶点的内存开销和合并前都是一样的。但是如果100个物体的Mesh完全一样,合并前只有一个Mesh的顶点数据,合并后就有100个同一个Mesh不同位置的顶点数据了,这种合并就会增大内存开销。所以我们在做森林等场景的时候面对大量的树的时候我们不使用静态合批。
根据实际的使用场景选择正确适合的合批方式就可以了。
附:学习视频地址
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-15 14:26 , Processed in 0.306223 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表