美文网首页
Unity Batches与glDrawElements的关系

Unity Batches与glDrawElements的关系

作者: 侑虎科技 | 来源:发表于2020-10-16 15:17 被阅读0次

    1)Unity Batches与glDrawElements的关系
    ​2)渲染大面积草地时,如何降低消耗
    3)HUD随着摄像机偏移
    4)Unity中如何在竖屏模式的UI之上显示强制横屏的UI
    5)iOS能耗问题


    这是第222篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

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

    Rendering

    Q:Unity里用FrameDebug显示DrawCall是422个,Batches是435个,在SnapDragonProfiler里抓取出来glDrawElements数目是1449个,怎么理解这种差异?

    A1:可参考以下几点:

    1. 题主的数据有一点问题,DrawCall数目应该大于等于Batches。根据特定的规则,多个DrawCall可以视为一个Batch,一个Batch中包含多个DrawCall,节省了一部分CPU提交数据的操作。
    1. 调用glDrawElements函数进行绘制就是DrawCall的一种形式。

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

    A2:这部分可以参考UWA Day 2020里张强老师的分享《Unity移动游戏项目优化案例分析(上)》中的第二小节。

    感谢范君UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5f33b10e9424416784ef1bdd


    Rendering

    Q1:渲染大面积草地时,如何降低消耗?

    A1:有以下几点:

    1. 使用DrawMeshInstance。
    2. 上面这个API是不会进行视距剔除,视锥体剔除和遮挡剔除的。

    下面有两种方案:
    a. 将草地按区域分组,用每组的中心点计算视距,依据距离切换网格LOD或剔除。
    还能用向量点乘简单剔除在相机后方的草地。(注意临界问题)
    b. 借助CullingGroup。
    CullingGroup.onStateChanged事件绑定,通过事件触发调整传入DrawMeshInstanced的Matrix顺序和渲染数量。(比较难的是,DrawMeshInstanced只能指定渲染前几个Matrix)

    通过cullingGroup.SetBoundingSpheres实现视锥体剔除和遮挡剔除;
    通过cullingGroup.SetBoundingDistances实现视距剔除和LOD;
    这个方案也最好进行区域分组,不然CullingGroup的事件监听占用会比较高。中端机上4000个监听会占约2ms。

    以后如果有对比两种方案的性能,我再进行补充。
    附:
    CullingGroup API的使用说明

    Unity 3D研究院之Lightmap支持GPU Instancing

    如何高效使用GPU Instancing技术来进行草丛渲染

    升级Unity 2018过程中,遇到的DrawMeshInstanced不生效的问题

    感谢题主李先生@UWA问答社区提供了回答

    A2:可以使用Indirect模式的Instancing,配合ComputerShader实现视锥剔除和遮挡剔除。

    感谢邹春毅@UWA问答社区提供了回答

    Q2:手机上能用吗?

    A:推荐一个使用URP制作的草海效果,亲测可在Mobile端使用。
    Unity URP Mobile Draw Mesh Instanced Indirect Example

    性能测试:

    • can handle 10 million instances on Samsung Galaxy A70 (GPU = adreno612, not a strong GPU), 50~60fps, performance mainly affected by visible grass count on screen(draw distance = 125)
    • can handle 10 million instances on Lenovo S5 (GPU = adreno506, a weak GPU), 30fps, performance mainly affected by visible grass count on screen(draw distance = 75)

    感谢Vest@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5e919a528cabe84a011afcde


    Rendering

    Q:HUD为什么会随着摄像机偏移?

    代码如下:

        Vector3 midVe1   = obj.transform.position;
        Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1 + new Vector3(0, 2, 0));
        viewPose.x *= Screen.width;
        viewPose.y *= Screen.height;
        hud.anchoredPosition = viewPose;
    
    

    图片如下:

    A:题主说的这个现象是合理的。

    Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1);
    Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1 + new Vector3(0, 2, 0));
    
    

    这两个算出来的viewPos.x是不一样的。所以可以改成先算x,再偏移y。大概是这样:

    Vector3 midVe1 = obj.transform.position;
    Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1);        
    viewPose.x *= Screen.width;
    viewPose.y *= Screen.height;
    viewPose.y += 130;
    hud.anchoredPosition = viewPose;
    
    

    这里面y方向上的偏移值(130)就要自己调整了。

    感谢Xuan@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5f804eff9424416784ef2587


    UGUI

    Q1:针对Unity中如何在竖屏模式的UI之上显示强制横屏的UI,我们现在有两种思路:

    1. 改Screen.orientation之后再显示。
    - 需要考虑外层RectTransform是否已经“完成”了转屏导致的变化,然后才能去适配内层。尚未找到可靠的事件。
    - 需要处理背景,半透明背景可能透出后面的UI排版混乱。

    2. 将新UI旋转依z轴转-90度显示。
    - 对刘海屏的适配需要做相应的修改。
    - 无法转屏(因为还是竖屏,且不支持Upside Down)。但是这个应该可以克服。

    请问,两者哪种更好呢?

    A1:一个简单的方式:
    Canvas的RenderMode改成World Space,管它摄像机怎么裁剪,UI画布也不会发生变化。

    如果自适应不了,在Canvas上根据你自己的需求做好自适应就好。

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

    A2:我们之前项目里刚好有个类似的需求,在横屏游戏中,个别玩法切换到竖屏。

    当时采用的解决方案是修改Screen.orientation,同时修改UI全局根节点上的CanvasScaler的referenceResolution(竖屏时设置为1080,1920,横屏设置为1920,1080),matchWidthOrHeight(和项目的适配策略相关,竖屏时设置为0,横屏时为1),切换时会有一个全屏遮罩的fade效果,来避免切换时显示错误。

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

    Q2:请问为什么不考虑转90度的做法?

    A:我们当时没有测过旋转的方案。现在大概想想有两个问题,不知道想的对不对。

    1. 单纯旋转角度应该只能在横屏的中间部分显示一个竖屏界面吧?感觉还需要其他处理。
    2. 对工作流是否有影响,如果要一个竖屏界面是否是要在制作时先做成一个横屏界面?内部控件是否要处理?例如最终呈现出竖屏效果的剧情文字从左到右出现,旋转之前应该是横屏的从下到上出现,同时每个单一文字也是旋转的。

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

    Q3:RectTransform的尺寸会被延迟修改这件事, 没有造成什么问题么?

    A:记不太清了,印象中没有遇到什么大问题。不过我们当时这类需求切换时都是全屏UI,加了遮罩Fade后没有什么明显的穿帮。

    感谢范君@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5f8166d99424416784ef25b0


    iOS

    Q:我在Xcode真机调试中发现能耗始终处于Very High,而我项目的基本情况是(每帧GPU渲染3.5ms,每秒60帧,渲染分辨率为750*1624,设备iPhone XS,场景中只有UGUI没有其它3D或2D物体),麻烦大家帮忙看看这个电量消耗属于正常吗?还有没有优化的空间(帧数和分辨率估计是没有办法下降了,会影响项目效果),谢谢。

    A1:测试过空场景Average Energy Impact也会显示Very Hight(如下图),题主的GPU能耗占比较大说明CPU相对而言还是压力比较小的:

    这个帖子也是类似的问题,看上去是因为Unity引擎本身相对于普通APP体量较大,所以能耗表现较高,降低目标帧率会有所改善。

    Energy Impact表征的是全局(非单个APP)的能耗,而且测试的时候USB连接充电是如何在统计中避免的不太清楚机制,建议使用Xcode Instruments工具的Energy Log模版测一下单个APP的能耗情况。
    Energy Log文档

    关于能耗的优化先关注整体的是GPU还是CPU(或其他方面),GPU的用FrameCapture定位一些比较高耗时的Shader进行优化,CPU结合Time Profiler模版定位一些高能耗的CPU Bound。

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

    A2:GPU的用FrameCapture定位一些比较高耗时的Shader进行优化。
    关键是Capture哪一帧,这个会很盲目。

    感谢山中千年@UWA问答社区提供了回答,欢迎大家转至社区交流:
    https://answer.uwa4d.com/question/5f81af2d9424416784ef2642

    封面图来源于网络


    今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

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

    相关文章

      网友评论

          本文标题:Unity Batches与glDrawElements的关系

          本文链接:https://www.haomeiwen.com/subject/kdvipktx.html