1)编辑器在编译Shader时的报错疑难
2)对于图片大小和包体大小的疑难
3)对于合图和合批是否会升高带宽的疑难
4)URP下,如何优化多相机渲染时的Cull耗时


这是第312篇UWA技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫10分钟,认真读完必有播种。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Shader

Q:有时在Shader编写过程中,咱们可能会用到十分多纹理,如果每个纹理都采纳相似uniform sampler2D \_Mask;的形式进行申明,编辑器在编译Shader的时候就会报错:

Shader error in ‘CloudShaow/MaskBlend’: maximum ps_4_0 sampler register index (16) exceeded at line 69 (on d3d11)

A1:OpenGL ES2.0中,单个Shader最多反对8个贴图;OpenGL ES3.0中,单个Shader最多反对16个贴图。没方法,这是硬件限度,你只能缩小贴图数量。

比方,把几个2D Texture合成2D Array Texture。或者,依据不同的Keyword,拜访不同的贴图,然而要保障,贴图使用量最多的变体,合乎下面的要求。

感激王烁@UWA问答社区提供了答复

A2:以前的写法,参考这个:
https://blog.csdn.net/weixin_...

当初的写法,只定义一个Sampler,传参数的时候共用这一个就行:

感激仇磊@UWA问答社区提供了答复

Resource

Q:对于图片大小和包体大小的疑难。

例如 ,一张图片,理论大小是1KB,放到Unity里是10KB(依据不同的压缩格局不一样),打包后查看Editor Log说图片占用了包体10KB。查了很多文章都说Unity打包的时候,会把图片按设定的压缩格局转成Unity的图片格式,但理论打出的包不是增长10KB,而是图片理论大小1KB,这个10KB是内存大小。

到底这个包体大小与图片大小的关系是怎么的?如何查看理论的包体资源形成?

A1:jpg和png领有良好的压缩率,也就是你所看到的1KB的图片。然而这2种格局不反对随机读取,所以引擎会帮你转换成反对随机读取的格局,会比原来的图片大一点,存储也是依照新格局来存储的。包体形成如果是AssetBundle或者全都放在Resource目录下,就能够通过AssetStudio进行解包查看。

感激萧小俊@UWA问答社区提供了答复

A2:你要了解内存大小和所占硬盘的容量大小,10KB是理论加载这张图内存会占用的大小,1KB是这个文件在你的操作系统中的文件所占的硬盘大小,然而不齐全等同于理论进包内的大小,毕竟Resource里或者打成AssetBundle之后会有肯定的压缩,能够在打下的AssetBundle中查看。

也就是说,要看下这个文件更改格局之后打进去的AssetBundle大小是否产生了本质的变动,因为AssetBundle的大小进到包内个别不会被压缩。

感激[email protected]问答社区提供了答复

A3:最终看打进去的AssetBundle包的大小即可,通常AssetBundle是不会2次压缩的,否则加载耗时会变高。纹理的压缩格局也会导致AssetBundle大小不一样,下图中是1024x1024的纹理测试失去的后果,仅供参考:

感激[email protected]问答社区提供了答复

Rendering

Q:对于合图和合批是否会升高带宽疑难。

有一张合图1024x1024,200个物体共用其中一张100x100纹理,总共DrawCall只有1,请问下当初带宽是:
200物体 x (1024 x 1024) or
200物体 x (100 x 100) or
1 x (1024 x 1024) or
1 x (100 x 100)?

如题目所说,合图的应该是被合成一个Batch,那是200物体 x (1024 x 1024)吗?

另外NxN的像素块有多大?比方想要渲染一张1024x1024背景图,个别会被读取几次?

若开启Mipmap,我的了解是相当于弄了一个合图,合图里蕴含了更低级别的信息。如果是这个思路,那合图传的带宽应该是100x100,而不是传整张合图1024x1024?

A1:首先一点,Sprite不是你想的100X100尺寸,传到GPU就是这块区域,最终传输到GPU还是纹理自身,GUI只是通过Sprite信息设置了顶点UV,能力正确渲染纹理的指标区域。Sprite它不是任何显示资源或者物理资源,而就是一个纯数据结构,为了方便管理一个纹理的不同区域。

感激1 9 7 [email protected]问答社区提供了答复

A2:纹理带宽次要指读纹理带宽:当GPU的OnChip Memory上没有,则会从System Memory外面读取,个别是会读取一个NxN的像素块的内容进OnChip Memory。所以,当采样次数和采样点更多的时候,越容易Cache Miss,这样就增多了到System Memory外面读取纹理到OnChip的次数,带宽就相应增大了。

因而,为了升高带宽,咱们常说纹理要开Mipmap,要缩小采样次数(防止开启各项同性和三线性差值),从而尽量减少Cache Miss次数;也能够进一步压缩纹理格局,来缩小传输的数据量。

对于本问题,实质还是在OnChip上读取外面NxN的内容的,然而会受到采样次数的影响。其中如果有200个DrawCall但被合成一个了Batch,依然会采样200次;但如果的确合成了一个DrawCall,那就会只采一次。

之所以说Mipmap升高带宽,是因为传到GPU的是适合层级的纹理,当画下一个像素时很大概率就落在OnChip里的NxN个像素内,就不须要从新采从而减少Cache Miss概率;但如果没有开Mipmap而导致用了分辨率过大的层级,则画两个相邻的点也可能要跨纹理中的好几个像素,从而得从新采从而减少Cache Miss概率。

感激[email protected]问答社区提供了答复

A3:对于带宽来说,是100x100还是1024x1024,区别不大,小图和大图的区别在于从CPU传到GPU的时候的操作,是一次性传图集到GPU外面还是分很屡次传小图到GPU,到带宽层面,都是读取采样点四周的像素到OnChip上,应该没有太大区别。至于采样点读取的NxN有多大,这个应该是和硬件相干。

感激[email protected]问答社区提供了答复

Rendering

Q:依据Profiler来看,CPU端相机的耗时有很大一部分在Cull阶段。有什么方法可能优化这部分的耗时吗?或者说跳过这部分?有尝试过通过CommandBuffer去绘制,然而CommandBuffer绘制的物体,SRPBatcher仿佛没法失效。

请问在URP下,多相机渲染时的Cull耗时有方法优化吗?

A:Frustum Culling曾经在JobSytem的子线程中。你相机可能反复渲染了,或者你场景的对象太多了,倡议先用些其余伎俩,比方LOD、HLOD或逻辑剔除等。

跳过不可能。如果跳过,全地图的顶点都会进入这一帧的VBO(一样会卡),EBO长度也大大增加 ,接着由驱动发送到GPU,起初来到Vertex Shader阶段参加计算(压力),其次除法前裁剪[-w,w]之外的顶点(最初也裁剪了,然而节约了最大的计算过程资源)。

感激龙跃@UWA问答社区提供了答复

封面图来源于网络


明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在UWA问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官网技术QQ群:793972859(原群已满员)