使用 CPU 增强《Star Trek™:Bridge Crew》的虚拟现实沉浸感

标题: 使用 CPU 增强《Star Trek™:Bridge Crew》的虚拟现实沉浸感 概览: 在虚拟现实 (VR) 细分市场中,环境交互、增强的物理模拟和摧毁的结合为游戏锦上添花,延长了玩家在游戏中花费的时间,增强了他们对游戏的兴趣。本文将向您逐一介绍《Star Trek™:Bridge Crew*》中实施的所有 CPU 密集型特性,提供用于使用基础系统的指令。 正文:

查看 PDF [2MB]

简介

一般而言,CPU 通常不是影响游戏中震撼的沉浸式场景的主要因素。过去,少数游戏将设置呈现给玩家,允许他们调整 CPU 使用,但是许多开发人员认为针对不同的硬件等级实施基于 CPU 的多层系统有些得不偿失。通过与 Ubisoft 的 Red Storm Entertainment* 工作室的通力合作,《Star Trek™:Bridge Crew*》得到了明显改进,我们的目标是借助本文纠正该误解。在虚拟现实 (VR) 细分市场中,环境交互、增强的物理模拟和摧毁的结合为游戏锦上添花,延长了玩家在游戏中花费的时间,增强了他们对游戏的兴趣。鉴于 Oculus* 所需的低端硬件规格,清除根据全球最低规格定制 CPU 工作的想法变得越来越重要。使用可用的系统资源增强动态性和沉浸感将帮助您创建理想的游戏,同时允许尽可能多的玩家访问,我们进行了前所未有的简化。

本文将向您逐一介绍《Star Trek™:Bridge Crew*》中实施的所有 CPU 密集型特性,提供用于使用基础系统的指令。后面的章节简要介绍了对于每个性能层级,认定 CPU 工作过量的标准。最后一部分展示了如何轻松设置 CPU 性能类别,以自动检测最终用户的硬件等级。

《Star Trek™:Bridge Crew*》通过 Unity* 创建,后者将是本文的重点,但是所有概念也适用其他引擎。

请观看以下视频,查看关于运行这些效果的游戏的详细对比。

《Star Trek™:Bridge Crew*》中的 CPU 密集型特性

舰桥破坏 – 结合了物理粒子、刚体物理和实时全局照明 (GI)

Sparks

概述

USS Aegis 的舰桥是游戏的主要焦点之一。几乎所有游戏环节均要求玩家在舰桥中完成,因此,显然应在舰桥中应用绝大多数 CPU 任务,从而为玩家带来超值的体验。大部分时间均消耗在改进舰桥的各种摧毁顺序,将强度元素添加至场景。例如,舰桥被摧毁后,大块碎片飞出,火光在墙壁和地板上飞溅,火势蔓延,照亮了周围物体,并不是从光源直接照射。

什么原因使它成为 CPU 密集型任务?

破坏舰桥充分使用了 Unity 的实时刚体物理、带有大量小粒子的粒子系统(启用碰撞支持)以及各种火焰和火花效果创建的实时全局照明 (GI) 更新,它们可在可用 CPU 内核上扩展。生成了在破坏事件中使用刚体物理的各种碎片对象,激活高端效果后,粒子数量大幅提高。添加了面向粒子的全局碰撞支持和碰撞基元,内含用于创建火花跳跃和分散行为的详细信息。添加了其他使用 CPU 的 Unity 粒子特性,以增强场景,如使用子发射器为火球或火焰添加拖尾。舰桥破坏粒子在屏幕覆盖尺寸中保持较小的外形,以将 GPU 影响降至最低,同时实现预期的外观。破坏事件发生时,某些光源和放射面将闪烁以模拟电源中断。光源闪烁且舰桥上的火焰激活后,更新 GI。下面,我们将进入每个系统,了解如何单独使用它们。

概述

Unity* 的内置粒子系统组件支持外观和行为的多种变化。恰巧,内置粒子系统在可用的 CPU 内核之间出色扩展。用户只需轻点按钮,便可引发粒子系统碰撞以及与环境响应,如果您需要一个高度自定义的行为,可以编写每个粒子运动的脚本(稍后将详细介绍)。使用以下内置碰撞行为时,底层引擎将工作分配给可用内核,支持最大限度扩展系统。因此,您可以基于可用内核的数量扩展粒子数量,同时还需考虑处理器频率和高速缓存大小。只需转至相关的粒子系统组件,检查碰撞复选框,然后选择所需的设置,便可激活粒子碰撞。

碰撞设置组中包括若干选项。您需要考虑选择与世界碰撞,还是定义一系列平面,使粒子与平面碰撞。第一种设置将产生最真实的模拟,因为场景中几乎所有碰撞器都将运行每个粒子更新计算,但是这必然会导致 CPU 成本增加。游戏通常会定义一系列关键平面,用来模拟周围地形,以尽量减少计算,为其他 CPU 密集型效果预留空间。您的设置选择取决于游戏布局和您想取得的视觉效果。例如,以下命令定义 3 个平面为碰撞器:一层地面和两面墙。

ParticleSystem[] ParticleSystems;
    public Transform[] CollisionPlanes;

    public void Awake()
    {
        ParticleSystems = gameObject.GetComponentsInChildren();
        Debug.Log("Initializing ParticleSystemController");
    }

public void SetCPULevel(CPUCapabilityManager.SYSTEM_LEVELS sysLevel)
    {
        for (int i = 0; i < ParticleSystems.Length; i++)
        {
            var particleSysMain = ParticleSystems[i].main;
            var particleSysCollision = ParticleSystems[i].collision;
            var particleSysEmission = ParticleSystems[i].emission;
            if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.HIGH)
            {
                particleSysEmission.rateOverTime = 400.0f;
                particleSysMain.maxParticles = 20000;
                particleSysCollision.enabled = true;
                particleSysCollision.type = ParticleSystemCollisionType.World;
            }
            else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.MEDIUM)
            {
                particleSysEmission.rateOverTime = 300.0f;
                particleSysMain.maxParticles = 10000;
                particleSysCollision.enabled = true;
                particleSysCollision.type = ParticleSystemCollisionType.World;
            }
            else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.LOW)
            {
                    particleSysEmission.rateOverTime = 200.0f;
                    particleSysMain.maxParticles = 5000;
                    particleSysCollision.enabled = true;
                    particleSysCollision.type = ParticleSystemCollisionType.Planes;
                    for (int j = 0; j < CollisionPlanes.Length; j++)
                    {
                        particleSysCollision.SetPlane(j, CollisionPlanes[j]);
                    }
                }
            else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.OFF)
            {
                particleSysEmission.rateOverTime = 100.0f;
                particleSysMain.maxParticles = 3000;
                particleSysCollision.enabled = false;
            }
        }

CPUCapabilityTester 示例中查看更多优化版本

实时全局照明 (GI)

概述

为了实现这个效果,请查看照明窗口 (Window > Lighting) 中的 实时照明 复选框 。 (注:实时 GI 的编辑器性能设置在 Unity* 的最新版本中隐藏,并在后台处理。脚本化 更新设置 仍然可用 – 参阅脚本以获取详细信息) 在 Unity* 早期版本中查看 预计算实时 GI 复选框 (同样位于  Window > Lighting 中)。 实时 分辨率 和  CPU 使用是严重影响 CPU 利用率的两个设置。

  • 实时 分辨率 确定每个单元应计算多少个纹理像素。 Unity* 发布的一篇教程 详细介绍了如何正确设置该值。根据实用的常规经验,视觉效果丰富的室内场景需要更多的每单元纹理像素,才能实现最逼真的效果。在广阔的室外场景中,间接的 光线 过渡并不明显,支持将 计算 能力用于其他地方。
  • CPU 利用率 确定了引擎中可用于实时 GI 计算的工作线程数量。最好能确定各种系统级别的可用 CPU 性能,  并以此作为设置的依据。对于低端系统,最好设置为低/中;高端 系统 建议设置为高或不限。关于这些设置的描述,详见与相应版本一同发送的 Unity* 文档。


Unity* 5.6.1f1 中的设置


旧版 Unity* 中的设置

void Start () {
        SetCPULevel(CPUCapabilityManager.Singleton.CPUCapabilityLevel);
    }

public void SetCPULevel(CPUCapabilityManager.SYSTEM_LEVELS sysLevel)
    {
        if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.HIGH)
        {
            DynamicGI.updateThreshold = 0;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.MEDIUM)
        {
            DynamicGI.updateThreshold = 25;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.LOW)
        {
            DynamicGI.updateThreshold = 50;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.OFF)
        {
            DynamicGI.updateThreshold = 100;
        }
        Debug.Log("(" + gameObject.name + ") System capability set to:" + CPUCapabilityManager.Singleton.CPUCapabilityLevel + ", so setting GI update threshold to:" + DynamicGI.updateThreshold);
    }

概述

实时 GI 模拟场景中光线的跳动与间接照亮对象。团队非常希望使用这个特性,因为 Aegis 前面的大窗户支持星体和破坏效果更新舰桥内部。在大型恒星或星云前移动 Aegis 改变了舰桥的外观,反射了入射光线,通过保持场景外观的一致和增强真实感,提供了更出色的沉浸式体验。

什么原因使它成为 CPU 密集型任务?

Unity 的* 实时 GI 消耗了大量的 CPU 计算资源,根据要求的逼真度使用部分可用内核。

是否内置于 Unity*?

是的。当启用实时GI效果时,应用程序用最高CPU使用率设置Unity *,允许立即更新速率以获得最佳效果。

动态小行星

云尾与太阳闪焰

如何实现

如果玩家的设备足够先进,可以启用 刚体 物理,将场景中的静态模型变为动态模型。通过 script 在已有对象中添加全新 刚体 组件或动态生成预配置对象的预制件,便可在脚本中实现该目标。动态对象和可交互对象在增强游戏(尤其是虚拟现实游戏)的沉浸感中发挥了巨大作用。

public GameObject[] PotentiallyDynamicObjects;
    int NumDynamicObjects = 0;
    void Start () {
        SetCPULevel(CPUCapabilityManager.Singleton.CPUCapabilityLevel);
    }
    public void SetCPULevel(CPUCapabilityManager.SYSTEM_LEVELS sysLevel)
    {
        if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.HIGH)
        {
            NumDynamicObjects = PotentiallyDynamicObjects.Length;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.MEDIUM)
        {
            NumDynamicObjects = PotentiallyDynamicObjects.Length / 2;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.LOW)
        {
            NumDynamicObjects = PotentiallyDynamicObjects.Length / 3;
        }
        else if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.OFF)
        {
            NumDynamicObjects = 0;
        }

        Debug.Log("(Obj:"+ gameObject.name + ") System capability set to:" + CPUCapabilityManager.Singleton.CPUCapabilityLevel + ", so setting number of dynamic objects to:" + NumDynamicObjects);

        for (int i = 0; i < NumDynamicObjects; i++)
        {

            Rigidbody objRigidBody = PotentiallyDynamicObjects[i].AddComponent<Rigidbody>();
            objRigidBody.useGravity = true;
            objRigidBody.mass = 10;
            PotentiallyDynamicObjects[i].AddComponent<CustomAsteroidMovement>();
        }
    }

是否内置于 Unity*?

动态小行星使用了 Unity* 的 刚体物理 和 粒子系统,但是生成小行星的系统由《Star Trek™:Bridge Crew*》团队编写与定制。查看以下示例,了解如何自行实施类似系统。

概述

当 Aegis 航行至小行星带时,将在玩家的视图体之外生成额外的小行星,并将它们发射到视图。这些小行星与已就位的小行星发生碰撞,并搅起尘埃。

许多游戏地图还包括小行星带生成器,将大量静态小行星分散在圆柱或球形区域。启用高端 CPU 效果后,舰桥移动时,这些区域将在舰桥特定距离以外放置应用刚体物理的动态小行星。用户会产生这样的印象:小行星带内遍布小碎片,它们相互碰撞,并与更大的行星相撞。由于速度已被用于维持物体运动与场景的活跃,产生一个动态行星带的可能性很小。最后,某些小行星与玩家的战舰或其他小行星碰撞后,将分解为更小的碎片,其它小行星将完好无损地反弹。

这些改变将用户的注意力从天空盒移开,使用户感觉自己身处太空;同时不中断游戏体验。

什么原因使它成为 CPU 密集型任务?

借助刚体物理使小行星带内漂浮着大量动态小行星碎片,实例化未合并的碎片以及在小行星解体后移动和生成额外碎片都使用了大量 CPU 时间。

概述

云尾制造了敌方战舰和 Aegis 通过太空时搅动尘埃的假象,增强了沉浸感。太阳闪焰通过将玩家目光从天空盒移开,使玩家认为自己身处遥远的太空,实现了相同的效果。

什么原因使它成为 CPU 密集型任务?

云尾与太阳闪焰使用了脚本化的粒子行为,该行为要求使用主线程上的脚本单独更新粒子。从循环数百个粒子到循环数千个粒子以及通过脚本更新属性占用了大量 CPU 时间,但是支持粒子的自定义行为,这是 Unity* 提供的即购即用普通粒子系统属性无法实现的。请记住,目前必须在主线程上完成,以防止系统像前面提到的粒子碰撞系统那样使用过多内核。请继续关注 Unity* 在 Unite Europe 2017 大会上提到的全新 C# 工作系统,后者将通过扩展 Unity* API 优化脚本代码中的多线程。

是否内置于 Unity*?

云尾和太阳闪焰使用了 Unity* 的粒子系统,但是 Red Storm Entertainment 通过编辑脚本,确定粒子如何随时间的推移而移动和改变。尾流效应使用一个粒子系统,从战舰的若干发射器点发射粒子拖尾。单个拖尾内粒子的大小和生命周期取决于它的发射器。拖尾粒子在世界空间内发射,但是发射器点一直附着于战舰,以确保在战舰转向与倾斜时也能从正确位置发射。定制粒子行为脚本在战舰后面添加虚拟“吸引器”对象,该对象通过随机振荡拉回附近的粒子,穿过云层时向战舰后面的拖尾引入湍流。太阳闪焰也使用吸引器行为向外散开粒子,或在向外发射粒子后,将其拉回太阳表面。以下简单示例展示了如何使所有粒子飞向世界起源点。

public ParticleSystem MyParticleSystem;
    ParticleSystem.Particle[] MyParticles = new ParticleSystem.Particle[4000];
    public float ParticleSpeed = 10.0f;

	void Update () {
        int numParticles = MyParticleSystem.GetParticles(MyParticles);

        for(int i = 0; i < numParticles; i++)
        {
            MyParticles[i].position = Vector3.MoveTowards(MyParticles[i].position, Vector3.zero, Time.deltaTime * ParticleSpeed);
        }

        MyParticleSystem.SetParticles(MyParticles, numParticles);
	}

摧毁战舰

如何实现

将模型建造为碎片,以各种断点作为间隔。为 Unity* 中包含网格渲染器的每个游戏对象配备一个 刚体 组件。对象被摧毁后,在每个网格上启用 刚体 组件,并将爆炸力应用到所有网格。如欲了解更多详情,请参阅 Unity* 的 刚体文档 。

// Explosion arguments
    public float ExplosiveForce;
    public float ExplosiveRadius;
    public Transform ExplosiveTransform;    // Centerpoint of explosion

    public Rigidbody BaseRigidBody;
    public GameObject[] PotentiallyDetachableCubes;
    List<Rigidbody> ObjRigidbodies = new List<Rigidbody>();
    bool IsCPUCapable = false;
    bool HasExploded = false;
	void Start ()
    {
        SetCPULevel(CPUCapabilityManager.Singleton.CPUCapabilityLevel);
    }

    public void SetCPULevel(CPUCapabilityManager.SYSTEM_LEVELS sysLevel)
    {
        // Only use if CPU deemed medium or high capability
        if (sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.HIGH
            || sysLevel == CPUCapabilityManager.SYSTEM_LEVELS.MEDIUM)
        {
            IsCPUCapable = true;

            // add rigidbodies to all little cubes
            for (int i = 0; i < PotentiallyDetachableCubes.Length; i++)
            {
                Rigidbody CurrRigidbody = PotentiallyDetachableCubes[i].AddComponent<Rigidbody>();
                CurrRigidbody.isKinematic = true;
                CurrRigidbody.useGravity = false;
                ObjRigidbodies.Add(CurrRigidbody);
            }
            Debug.Log("(ExplosionController) System capability set to:" + CPUCapabilityManager.Singleton.CPUCapabilityLevel + ", so object (" + gameObject.name + ") is destructible");
        }
        else
        {

            Debug.Log("(ExplosionController) System capability set to:" + CPUCapabilityManager.Singleton.CPUCapabilityLevel + ", so object (" + gameObject.name + ") not destructible");
        }
    }

    public void ExplodeObject()
    {
        HasExploded = true;
        if (IsCPUCapable)
        {
            BaseRigidBody.useGravity = false;
            BaseRigidBody.isKinematic = true;
            BoxCollider[] BaseColliders = GetComponents<BoxCollider>();
            for(int i = 0; i < BaseColliders.Length; i++)
            {
                BaseColliders[i].enabled = false;
            }
            for (int i = 0; i < ObjRigidbodies.Count; i++)
            {
                Rigidbody CurrRigidbody = ObjRigidbodies[i];
                CurrRigidbody.isKinematic = false;
                CurrRigidbody.useGravity = true;
                CurrRigidbody.AddExplosionForce(ExplosiveForce, ExplosiveTransform.position, ExplosiveRadius);
                ObjRigidbodies[i].gameObject.AddComponent<BoxCollider>();
            }
        }
        else
        {
            // Boring destruction implementation
            BaseRigidBody.AddExplosionForce(ExplosiveForce, ExplosiveTransform.position, ExplosiveRadius);
        }
    }

    void OnCollisionEnter(Collision collision)
    {
        if(!HasExploded)
        {
            ExplosiveTransform.position = collision.contacts[0].point;
            ExplodeObject();
        }
    }

概述

战舰摧毁特性使玩家击败敌人时满足感倍增,从而增加了游戏的刺激性。在游戏中,一般会通过爆炸效果遮挡爆炸对象,以掩饰从场景中删除废弃 游戏对象时使用的 popping 效果。借助高端配置中的 CPU 性能,我们可以将模型分成若干部分,朝不同方向发射,甚至可以添加子摧毁。每个碎片都可以与场景装置相撞,最终消失或停留(如果系统能够处理)。

什么原因使它成为 CPU 密集型任务?

艺术家将战舰分解为包含刚体组件的多个不同部分,初始化各个部分后通过物理力制作动画。启动与其他对象(如小行星或战舰)的碰撞,以确保在动画环境中显示逼真的行为。此外,战舰的每块爆炸碎片都添加了粒子拖尾。

是否内置于 Unity*?

该特性的刚体和物理属性完全内置,使用针对 Unity* 的方法添加爆炸力至战舰碎片。随后制作动画,并借助 Unity* 的刚体物理系统与对象碰撞。Unity* 粒子系统用于发射带有子发射器的粒子,以在碎片后面创建拖尾,但是最高级别的粒子位置由脚本管理,以确保它们依附于爆炸的战舰碎片,无需担心父项的坐标空间。

CPU 性能检测插件

我们已经介绍了《Star Trek™:Bridge Crew*》中添加的所有特性,但是,如何确定目标系统能处理哪些特性?为了尽量减少麻烦,我们创建了一个易于使用的 Unity*插件(包含源代码)。代码附有面向 Unity* 和原生实施的示例代码,用作一个工具盒,为您提供帮助定义目标系统类型的系统指标。上文的许多示例已经集成至样本,方便用户使用。包括以下步骤:

  1. 定义您的 CPU 性能级别。
        public enum SYSTEM_LEVELS
        {
            OFF,
            LOW,
            MEDIUM,
            HIGH,
            NUM_SYSTEMS
        };
       
  2. 设置 CPU 值阈值。插件提供了各种指标,如逻辑/物理内核数量、最大频率、系统内存等。但是,如果您想考虑其他因素,可以随时添加其他指标。对于多数基本使用,提供的指标应该够用。
            // i5-4590
            LowSettings.NumLogicalCores = 4;
            LowSettings.UsablePhysMemoryGB = 8;
            LowSettings.MaxBaseFrequency = 3.3;
            LowSettings.CacheSizeMB = 6;
    
            // i7 - 7820HK - Set to turbo mode
            MedSettings.NumLogicalCores = 8;
            MedSettings.UsablePhysMemoryGB = 8;
            MedSettings.MaxBaseFrequency = 3.9;
            MedSettings.CacheSizeMB = 8;
    
            // i7-6700k
            HighSettings.NumLogicalCores = 8;
            HighSettings.UsablePhysMemoryGB = 8;
            HighSettings.MaxBaseFrequency = 4.0;
            HighSettings.CacheSizeMB = 8;
    
  3. 初始化插件并确定用户是否运行英特尔® 处理器。
    void QueryCPU()
        {
            InitializeResources();
            if (IsIntelCPU())
            {
                // Your performance categorization code
            }
            else
            {
                Debug.Log("You are not running on an Intel CPU");
            }
        }
    
    
  4. 询问目标系统。
    StringBuilder cpuNameBuffer = new StringBuilder(BufferSize);
                GetProcessorName(cpuNameBuffer, ref BufferSize);
                SysLogicalCores = GetNumLogicalCores();
                SysUsablePhysMemoryGB = GetUsablePhysMemoryGB();
                SysMaxBaseFrequency = GetMaxBaseFrequency();
                SysCacheSizeMB = GetCacheSizeMB();
    
  5. 对比阙值,以确定测试系统属于前面定义的何种性能级别。
        bool IsSystemHigherThanThreshold(SystemThreshold threshold)
        {
            if (threshold.NumLogicalCores < SysLogicalCores && threshold.MaxBaseFrequency < SysMaxBaseFrequency
                && threshold.UsablePhysMemoryGB < SysUsablePhysMemoryGB && threshold.CacheSizeMB < SysCacheSizeMB)
            {
                return true;
            }
            return false;
        }
    
    SYSTEM_LEVELS MySystemLevel = SYSTEM_LEVELS.OFF;
    
    if (IsSystemHigherThanThreshold(HighSettings) || IsWhitelistedCPU(SYSTEM_LEVELS.HIGH))
            {
                MySystemLevel = SYSTEM_LEVELS.HIGH;
            }
            else if (IsSystemHigherThanThreshold(MedSettings) || IsWhitelistedCPU(SYSTEM_LEVELS.MEDIUM))
            {
                MySystemLevel = SYSTEM_LEVELS.MEDIUM;
            }
            else if (IsSystemHigherThanThreshold(LowSettings) || IsWhitelistedCPU(SYSTEM_LEVELS.OFF))
            {
                MySystemLevel = SYSTEM_LEVELS.LOW;
            }
            else
            {
                MySystemLevel = SYSTEM_LEVELS.OFF;
            }
    
            Debug.Log("Your system level has been categorized as:" + MySystemLevel);
    

性能分析与注意事项

和 GPU 工作相同,我们需要验证特性集的组合 CPU 利用率没有超过目标,以持续提供异步空间扭曲(极力避免 Star Trek™ 的双关语)和二次投影触发器。我们想要确保无论运行于何种设备,游戏的每秒帧数能维持在 90,同时最大限度地使用 CPU。《Star Trek™:Bridge Crew*》团队决定将特性集分为 3 个等级:OffPartialFull。因此,我们在匹配 Off 阙值的设备上测试了Full 组特性。


GPUView 显示配备 HSW i5-4590 CPU + GTX 1080 GPU 的台式机系统的工作分布

CPU显卡场景配置运行更新周期新帧掉帧生成的合成帧

HSW i5-4590

GTX1080

任务 5,初始弯曲之后

完整设置

1

11861

5993

58

5810

2

11731

6584

56

5091

3

11909

6175

101

5633

 

 

平均值

11833.67

6250.67

71.67

5511.33

生成的合成帧数不为零,表示在低端 CPU 上完整特性集的 CPU 工作超过每帧 11.1 毫秒的阙值

以上 GPUView 截屏显示从 presentpresent 耗时约 22 毫秒(突出显示)。Present 表示最后帧已生成并且为提交至 头盔显示器 (HMD) 做好准备的时间,可以从帧速率(转换为 45 fps)的角度理解。从 90 到 45 fps 意味着我们正不断通过运行于“Off”级系统的配置触发 ASW。查看任务 5 的 3 次测试运行,我们发现 ASW 触发器平均生成了约 5500 个合成帧。将这些沉浸式特性集成至 Oculus min-spec 便失去了效果,这和我们预想的一致。我们没有在所有配置中删除特性集,而是将特性集绑定运行时可确定的硬件级别,以激活合适的特性集,为不同硬件级别的玩家提供最佳游戏体验。如果查看运行于高端目标(英特尔® 酷睿 i7-7700K 处理器)的相同配置,会发现不同的结果。


GPUView 显示搭载 KBL i7-7700K CPU + GTX 1080 GPU 的台式机系统上的工作分布

CPU显卡场景配置运行更新周期新帧掉帧生成的合成帧

KBL i7-7700k

GTX1080

任务 5,初始弯曲之后

完整设置

1

11703

11666

37

0

2

11654

11617

37

0

3

11700

11672

28

0

 

 

平均值

11685.67

11651.67

34.00

0.00

生成的合成帧数为零,表示高端 CPU 上完整特性集的 CPU 工作未超过每帧 11.1 毫秒的阙值

借助高端目标提供的额外的逻辑内核、更高的频率和更大的高速缓存,所有工作都将扩展,并能在 11.1 毫秒的规定时间内完成,以达到 90 fps 的帧速率。整个过程中,CPU 工作的平均每帧持续时间在 9-10.3 毫秒之间。这意味着高端目标的性能几乎达到了极限,但是仍维持稳定的 90 fps,并使用了所有的可用资源。我们达到了最佳结果!我们完成了“Off”和“Full”特性集的测试。此时,我们需要选择“Full”特性集中的一个子集,并在基于英特尔酷睿 i7-7700HK 处理器的 VR 就绪型笔记本电脑上启用该子集。这是“Partial”特性集的中间目标。我们希望保留真正影响舰桥内部的特性,因此我们提高这些特性的优先级,然后逐一移除其他特性,直到得到最佳结果。最终,我们只需移除动态尾流效应和动态小行星,便可在笔记本电脑上轻松实现 90 fps 的帧速率。以下 GPUView* 截屏显示了运行于 VR 就绪型测试笔记本电脑的“Partial”特性集。


GPUView 显示搭载 KBL i7-7820HK CPU + GTX 1080 GPU 的虚拟现实游戏笔记本电脑上的工作分布

CPU显卡场景配置运行更新周期新帧掉帧生成的合成帧

KBL i7-7820HK

GTX1080

任务 5,初始弯曲之后

完整设置

1

11887

11242

116

529

2

11881

11315

110

456

3

11792

10912

125

755

 

 

平均值

11853.33

11156.33

117.00

580.00

生成的合成帧数不为零,表示在 VR 就绪型笔记本电脑上完整特性集的 CPU 工作超过每帧 11.1 毫秒的阙值

CPU显卡场景配置运行更新周期新帧掉帧生成的合成帧

KBL i7-7820HK

GTX1080

任务 5,初始弯曲之后

部分设置

1

11882

11844

38

0

2

10171

10146

25

0

3

11971

11933

38

0

 

 

平均值

11341.33

11307.67

33.67

0.00

生成的合成帧数为零,表示在 VR 就绪型笔记本电脑上部分特性集的 CPU 工作未超过每帧 11.1 毫秒的阙值

结论

总体而言,更逼真、更高分辨率的模拟以及更多动态实体的使用是 CPU 利用率上升的主要原因;现在可以在许多 CPU 上启用之前较昂贵的物理模拟。此外,可以使用动画/反向运动学 (IK)、布料模拟、群集、流体模拟、程序生成等其他 CPU 密集型系统生成更丰富、更逼真的世界。行业内已存在面向显卡的设置级别,现在我们应着手考虑为 CPU 设置划分级别。开发游戏时,请思考各个硬件级别上未被充分挖掘的所有计算潜能,考虑如何利用这些潜能使游戏变得与众不同。如欲获取更多信息,请点击以下链接。尽情探索。

  • 特别鸣谢 Kevin Coyle 和 Red Storm Entertainment 团队的其他成员,他们与我们通力合作,协助文章的完成**

其他资源

“发挥震撼的显卡性能:使用 CPU 增强《Star Trek™:Bridge Crew》的虚拟现实沉浸感”

作者在 Unite 2016 大会上展示了文章的信息。

会议描述 – 如今,许多游戏和体特别强调 GPU 工作,但是内置于现代主流 CPU 的多核处于闲置状态。此演讲探索了 Ubisoft 的 Red Storm 工作室和英特尔如何通过使用 Unity* 在《Star Trek™:Bridge Crew》中提供最卓越的沉浸感,以充分利用可用资源。了解如何在您的游戏中实现震撼的视觉效果,同时将对 GPU 的性能影响降至最低!

Catlike 编码

Catlike 编码提供众多出色的 CPU/数学密集型教程,任何人可以轻松掌握与运行。本教程以 Unity* 为主,但是由于内容不依赖任何特定的 API,因此适用于所有引擎。强烈推荐对程序生成、曲线/样条使用、网格变形、纹理处理、噪声等感兴趣的用户使用该教程。

面向视频游戏的流体模拟(系列)

本文是一篇编写出色的教程,介绍了如何实施面向视频游戏的多核流体模拟。本文非常适合初学者,涵盖了从概念到实施的所有信息。文章结尾处将提供源代码,读者可以将其添加至引擎,了解如何使用代码模拟各种流体类型。

链接:https://software.intel.com/zh-cn/articles/fluid-simulation-for-video-games-part-1

有关编译器优化的更完整信息,请参阅优化通知