乐趣区

关于rendering:关于CameraDepthTexture的疑惑

1)对于_CameraDepthTexture 的纳闷
​2)贴图 Alpha 通道对图片大小的影响
3)URP 要怎么实现 GrabPass 的成果
4)如何获取 AssetDatabase 加载失败的 Asset 的 Instance ID
5)如何判断 Bundle 文件加载进内存的机会


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

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

Rendering

Q:一个对于_CameraDepthTexture 的疑难。

如果开启_CameraDepthTexture,Camera 就须要渲染一遍场景内所有带有 ShadowCaster 的可见物体的 Pass 来实现深度图。

然而场景中的物体在开启 ZWrite 的时候就把深度写进了 Depth Buffer 中了,间接取得这个 Depth Buffer 是不是比近乎 DrawCall 翻倍的形式更有效率呢?还是 Unity 在这方面有什么思考?

另外,问一个更理论的问题:
咱们的我的项目须要渲染场景的中湖水的深度成果,所有不通明的场景物体的材质都是关联同样一个 Shader,这个 Shader 是带有 ShadowCaster 的。然而只有个别插入水中的物体须要去渲染 ShadowCaster 的 Pass,有没有办法在不减少 Shader 的状况下,让没有插入水里的物体不渲染 Shadow Caster Pass 呢?咱们用的是 Built-in 的渲染管线。

A:第一个问题,能够参考这个问题中 Unity 官网人员的回复。
外面讲了两个起因,第一是对于非全屏渲染的状况,原本是想拿对应相机渲染的深度,然而 Depth Buffer 是全屏的。第二个起因是因为很多平台不反对间接拿 Depth Buffer 的数据。

参考网页:
https://forum.unity.com/threads/poor-performance-of-updatedepthtexture-why-is-it-even-needed.197455/

另外查 FrameBufferFetch 相干问题的时候看到 Unity 论坛上另外一个贴子外面的答复。外面说到 Unity 反对了 FrameBufferFetch,然而不反对 DepthBuffer 的获取。

参考网页:
https://forum.unity.com/threads/pixel-local-storage-and-frame-buffer-fetch-on-mobile-devices.604186/

第二个问题,如果不减少 Shader,目前没想到其余好的办法。
如果能够减少 Shader,能够将原来的 Shader 复制一份,只在 ShadowCaster 的局部加一个“NeedDepth”这样的 Tag,将水下的物体的材质球换成这个 Shader,另外做一个只有 ShadowCaster 并带有“NeedDepth”这个 Tag 的 Shader,这个 Shader 用来做 Replace 操作。

额定减少一个 Camera,这个 Camera 追随主相机,或者作为主相机的子节点,创立一个 RT,让这个 Camera 渲染到这个 RT,在 Update 外面应用 ReplaceShader 去画一下,那么只有有那个 Tag 的 ShadowCaster 会进行深度渲染,后续能够对这个 RT 进行编码等操作,这个 RT 记录的就是水下物体的深度。整个过程看上去没有特地多的额定工作,感觉能够一试(我没有做过测试,但实践上是可行的)。

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


Texture

Q:在 UWA 的《纹理优化:不仅仅是一张图片那么简略》这篇文章中,形容了图片含有 Alpha 通道会对内存有影响。

通过以下的测试资源配置:

  • Tga_Alpha – 含有 Alpha 通道
  • Tga_NoAlpha – 不含有 Alpha 通道
  • Png_Trans – 含有通明的图片
  • 进入到 Unity 中的 Format,全副代码设置为 TextureImporterFormat.ASTC_6x6

测试后果:

  • 三张图片 Unity 全副 Format 为下图格局
  • 三张图片显示的内存大小全副一样
  • Texture Importer 的 Alpha Source 设置为 None,对测试后果无影响

    问题:图片是否含有 Alpha 通道,对于同一个 Format 格局,内存大小都是一样的吗?
    Tex.7z

A:原文中的优化倡议是去除无意义的 Alpha 通道(原文中的定义为 Alpha 值全副为 1 的贴图),这个的确是对内存优化有帮忙的。

题主的测试用例中,无论是 png 格局还是 tga 格局,进入引擎后,都会被引擎转为外部的格局(RGBA、ETC、ASTC 等)。构想一下,以 ETC2 为例,如果没有 Alpha 通道,在压缩品质能够承受的状况下,就能够选用 RGB_Compressed_ETC2_4bits,而如果增加了这个无意义的 Alpha 通道,那么咱们在批量导入设置时,都会主动抉择 RGBA_Compressed_ETC2_8bits。这样内存就相差了一倍。

而问题中对于 ASTC 的状况,在 Unity 编辑器源码中的 Texture 导入格局的定义有这样一句正文:// ASTC uses 128bit block of varying sizes (we use only square blocks). It does not distinguish RGB/RGBA,即与是否蕴含 Alpha 通道无关。对于 ASTC 格局的介绍,这里举荐你浏览一下 Github 上的 ASTC Format Overview。

而对于你楼上回复中提到的 Unity 新版本的问题,能够看下 Unity 论坛上的这个问题。

可能有人感觉对于我的项目的贴图格局都是 ASTC 来说,去除 Alpha 的意义不是很大,其实不能一概而论,尽管大小雷同,但依据(https://zhuanlan.zhihu.com/p/158740249)中的测试,是否有 Alpha 通道会肯定水平上影响压缩品质。所以还是要在我的项目中正当应用。

感激范君 @UWA 问答社区提供了答复

A2:游戏运行时 Texture 的 Alpha 通道要看导入后的状况,不能看源文件的状况。UWA 本地资源检测对于 Texture 的 Alpha 通道检测的就是导入后的后果。

图片源文件的格局,图形硬件是不反对的,Unity 也不间接接管。导入图片后,会依照 Import Settings 中的设置对图片进行解决,将图片导入成硬件反对的格局(在引擎中的格局),而在运行中应用的资源也是导入后的。

题主将 Alpha Source 设置为 None,那么导入时就不对源文件的 Alpha 通道进行导入,而压缩格局为 ASTC_6x6,这个格局是蕴含 Alpha 通道的。这样导入后三个资源都会默认生成一个全为 1 的 Alpha 通道。占用内存大小天然一样。

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


Rendering

Q:URP 如何实现 GrabPass 的成果?URP 管线曾经去掉了原先 GrabPass 的性能,当初有一个扭曲特效的性能,相似热扰动那种。尽管 URP 可能间接获取到实体图做扭曲成果,然而像是半透明物体(比方:水、其余特效等)也须要被扭曲就做不到。

A:题主想要齐全实现 GrabPass 预计不行,然而能够有代替计划:

GrabPass 的意思就是先绘制 a 物件,而后绘制 b 物件的时候影响 a,绘制 c 物件的时候影响 ab。留神,这最重要的是 b 物件的扰动影响不了 c 物件,因为 b 物件是比 c 物件先绘制的。

然而如果你可能承受 b 物件和 c 物件的扰动同时影响 abc,那么就简略了,先用一个 RT 将扭曲的信息存下来(其实就是 UV 偏移),而后在 Uber Shader 中将偏移利用在画面上。这样扭曲信息就扰动了所有物件(不论是不通明还是半透明)。

尽管不晓得 URP 怎么实现的,然而咱们本人改的 SRP,就是这么实现的。

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


Editor

Q:当初有一个继承于 ScriptableObject 的 Asset,无论出于什么起因,援用脚本的 GUID 错了。那么通过肯定的编辑器脚本能找到这个 Asset 的 Path,然而如何在 ProjectView 内选中它?

经测试,应用 Selection.instanceID 是能够选中的,而 Instance ID 个别须要通过 Object 来获取,然而因为脚本援用谬误了,所以 AssetDatabase 是无奈载入这个 Object 的。有什么方法或者 API 能获取到这个 Instance ID 呢?

A:通过查看公开源码,找到了一个可用的办法:

//assetPath : 某个找不到对应脚本的 Asset 实例门路
HierarchyProperty property = new HierarchyProperty(assetPath);
Selection.activeInstanceID = property.GetInstanceIDIfImported(); 

这样能够在 ProjectView 内正确选中了。

感激题主黄程 @UWA 问答社区提供了答复


Addressable

Q:当下载好所有的资源后,在一个测试脚本中调用 LoadAssetAsync 函数,如下图:

在 AssetBundleProvider 这里是第一个纳闷:
既然 Addressables 全副采纳缓存机制来寄存 AssetBundle 包,那此处的 File.Exists 不是总会为 False 吗?

第二个纳闷在于:
Addressables 在 WebRequest 实现下载后,如何把握把 Bundle 加载进内存的机会?也可能是我的思路有问题,然而在前面的堆栈追踪外面没有发现有相似于 LoadFromFile 这样的调用。

A:这儿的 File.Exists 并不是查看缓存,而是查看文件在不在 StreamingAssets 外面。而所有下载的资源则是通过缓存来获取的,若缓存里没有则下载。而 Load 这部分曾经被封装在了 UnityWebRequestAssetBundle 内了。

感激黄程 @UWA 问答社区提供了回:

封面图来源于网络


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

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

退出移动版