如何把握卡通渲染的制作流程?

如何把握卡通渲染的制作流程?

本期聚集话题:卡通渲染的制作流程、没用物理模块,为什么还会有物理引擎的耗时?SpriteAtlas的late bind机制、ASTC在安卓平台使用的可行性、UI 性能分析...


这是第106篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间15分钟,认真读完必有收获。文末,我们的互动话题是:资源的同步和异步加载,哪个更受你的青睐,我们期待你的灼见!

UWA 问答社区:answer.uwa4d.com
UWA QQ群:793972859(仅限技术交流)

本文封面图来源:ACT手游《崩坏3》
https://www.bh3.com/picture.html


制作

Q1:我最近在Unity中制作角色的卡通渲染效果,目前的工作流程是这样的:1)程序在Unity中写Shader调效果;2)美术在3dmax修改模型顶点色和法线等资源,修改完导出给程序;3)程序将资源导入Unity中验证效果。目前需要频繁地修改资源、导出导入资源,效率比较低下。

所以我有以下两个问题:
1、如何在3ds max中写着色器,美术修改模型后能及时看到效果?
2、成熟的制作流程是什么样的?

A1:这个不难的,让渲染程序员简单看一下Maya或者Max的文档,几个小时基本都是可以搞定的,Max或者Maya都有例子和文档,比如Max的话就是用DirectX Shader Material,不用把这个想得很难,好好看文档。

我觉得本质上主要是想要所见即所得,所有的工作也都是为了这个目的。卡通渲染对美术资源的修改大多需要定制化,例如靠刷顶点色控制描边,靠改顶点法线去改善光照,所以如果把Shader做到Max里可以大大提高美术的制作流程,而不是总是导入导出。通常的流水线是:维护一个和引擎预览效果一致的Max(或Maya)Shader材质,再加一个自定义的法线编辑工具(如果美术觉得内置的不够用,比如Max的法线编辑比较困难),这样在修改美术资源保证效果一致性就好了。

感谢乐乐@UWA问答社区提供了回答

题主补充:对于第一个问题,读书哥提供了一个方法:Max里可以用HLSL写,有DX9/11的Sample,但是问题挺多的,Driver建议用Nitrous Direct 3D 9,记得关掉Gamma/LUT和SSAO。

附上参考文档链接:http://docs.autodesk.com/3DSMAX/16/ENU/3ds-Max-SDK-Programmer-Guide/index.html?url=files/GUID-0C7A600E-7954-42B0-86EE-586A379A2CAD.htm,topicNumber=d30e34269

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5ac0dbc1910222635366dc85


UI

Q2:我们打开UI界面Profiler峰值显示 Canvas.SendWillRenderCanvases消耗了50%CPU开销,Canvas.SendWillRenderCanvases 消耗80ms,Graphic.Rebuild 消耗了72ms,请问有什么办法可以优化呢?

UWA:这是某个/某些大量的UI界面元素的重建开销,建议如下:
(1)先通过“动静分离”原则检测是否有不必要的静态UI网格参与了重建;
(2)UI界面是否过于复杂,UI层级或者网格量是否过大;
(3)在UWA性能简报中查看对应的解决方案和相关视频,磨刀不误砍材工。下图中可以看到这些参数在每次测评中的走势,耗时下降的很快:)
请输入图片描述

该问题由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5ac49b99910222635366dca9


物理

Q3:如下图,我们物理模块中没有用到任何碰撞对和Rigidbody,为什么还会有物理模块的耗时呢?
请输入图片描述
请输入图片描述

UWA:题主的Unity版本是多少的?如果是Unity 5.4版本以后,那确实不太正常,因为Unity引擎在5.4后对物理系统做了调整。

如果是Unity 5.4之前版本,那么就是比较正常了,因为无论你是否使用,物理模块每帧都在运转,你可以理解为是空转。对此,题主需要查看报告中“重要参数解析->引擎性能参数”中的“Physics.Processing”或“Physics.Simulate”一页,里面有这两个函数的调用次数。很多时候,物理模块即便没怎么用,但由于是每20ms运行一次(默认情况下),也会在同一帧中运行很多次,如下图所示。所以,物理模块有个特点,就是当你项目卡的时候,它会让你的项目更卡:)对于这种情况,题主只需要去优化其他模块,当其他模块的耗时下来后,你会发现物理模块的耗时自然也就下来了。
请输入图片描述

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5ac4e681910222635366dcbd


资源管理

Q4:我最新在使用Unity 2018.1.0 Beta 13的版本碰到一个问题,不过我相信低版本也可能有同样的问题。我使用Unity 2017新出的SpriteAtlas进行Sprite打包,并且生成了AssetBundle,发现这种方式和tag不一样,自己还需要处理延迟绑定,因此需要自己去实现SpriteAtlasManager.atlasRequested的回调。

于是我将所有SpriteAtlas的Include Build都去掉,打包了AssetBundle,但是在实现SpriteAtlasManager.atlasRequested碰到一个问题:如果我使用同步接口,也就是AssetBundle.LoadFromFile和AssetBundle.LoadAsset的接口加载SpriteAtlas,并且在SpriteAtlasManager.atlasRequested内部就直接回调action,则不会有问题;如果我使用异步接口,也就是AssetBundle.LoadFromFileAsync以及AssetBundle.LoadAssetAsync,等加载完成之后再回调action,也就是在SpriteAtlasManager.atlasRequested以外,则会导致图片无法加载,无论是编辑器还是打包出来(我测试的Windows的包),都会导致UGUI界面是花的。

我在官方咨询但是没有结果:https://forum.unity.com/threads/spriteatlasmanager-atlasrequested-is-not-invoked-in-editor.524801,想请教一下这个算是Unity的Bug还是我的某些理解操作有问题导致的?

UWA:首先“发现这种方式和tag不一样,自己还需要处理延迟绑定”,这里并不是必须的,如果勾选了Include in build,是不需要自己处理binding的,直接加载实例化就可以了。只是需要注意这个Bug,目前会导致Bundle中图集冗余:https://answer.uwa4d.com/question/5a822325847802258a06509e

如果题主就是希望做late binding的,那么从题主的描述中看,应该是说SpriteAtlasManager.atlasRequested中必须直接回调action才有效,用了异步(相当于隔了几帧)之后才回调action就无效。

所以做了个例子尝试复现,但没有出现类似的问题,下面是测试代码,UI Prefab(里面用到了某Sprite)和对应的SpriteAtlas做依赖打包,分别记为prefabBundle和saBundle。加载的代码如下,版本是2017.2.2。

IEnumerator Start ()
    {
        var loadOp = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + prefabBundle);
        yield return loadOp;
        var prepre = loadOp.assetBundle.LoadAsset<GameObject>("prop_parachute");
        GameObject.Instantiate(prepre);
    }
    void OnEnable()
    {
        SpriteAtlasManager.atlasRequested += RequestLateBindingAtlas;
    }
    void OnDisable()
    {
        SpriteAtlasManager.atlasRequested -= RequestLateBindingAtlas;
    }
    void RequestLateBindingAtlas(string tag, System.Action<SpriteAtlas> action)
    {
        StartCoroutine(LoadFromAssetBundle(tag, action));
    }
    IEnumerator LoadFromAssetBundle(string tag, System.Action<SpriteAtlas> action)
    {
        var loadOp = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + saBundle);
        yield return loadOp;
        var loadOp2 = loadOp.assetBundle.LoadAssetAsync<SpriteAtlas>(tag);
        yield return loadOp2;
        var sa = loadOp2.asset as SpriteAtlas;
        action(sa);
    }

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5ac430f0910222635366dc99


资源管理

Q5:当下ASTC在安卓平台使用的可行性是如何的呢?官方文档所说, 几个主流GPU支持ASTC的要求都不高,请问在安卓设备上使用ASTC还有其他什么需要注意的吗?
请输入图片描述

就 ASTC压缩方式本身来说是没有问题的。对纹理尺寸无要求,支持多个品质等级。但问题在于 OpenGL ES 3.2 以后才支持,也就是一大批中低端机就没戏了。比如红米2,小米4。iOS 平台的 iPhone 6 之后才支持。不支持的结果就是纹理会自动转成 RGB24/RGBA32。所以我们项目尝试了一下 ASTC 又用回 ETC2 了。

感谢史亚征@UWA问答社区提供了回答

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5ac2eb4c425802635474fbef


互动话题

资源的同步加载和异步加载,你更倾向于哪种方式?你是否有什么高见呢?

期待你的分享哦!