Bevy 0.6

发布于 2022 年 1 月 8 日,作者 Carter Anderson ( 一个戴着猫耳朵、挥舞触手的卡通人物,或 Octocat:GitHub 的吉祥物和 logo @cart 一只灰色鸟飞行的矢量图;X(前身为 Twitter)的旧 logo @cart_cart 一个指向右边的三角形,在一个圆角矩形里;Youtube 的 logo cartdev )

The Lumberyard Bistro scene rendered in the New Bevy Renderer by @mockersf
Lumberyard Bistro 场景,由 @mockersf 在新的 Bevy 渲染器中渲染

感谢 170 位贡献者、623 次拉取请求,以及我们 慷慨的赞助者,我很高兴地宣布 Bevy 0.6crates.io 上发布!

对于那些不知道的人来说,Bevy 是一个用 Rust 构建的,令人耳目一新的简单数据驱动的游戏引擎。你可以查看 快速入门指南 来开始使用。Bevy 也是永远免费和开源的!你可以在 GitHub 上获取完整的 源代码。查看 Bevy 资产,它包含了一系列由社区开发的插件、游戏和学习资源。

要将现有的 Bevy 应用或插件更新到 Bevy 0.6,请查看我们的 0.5 到 0.6 迁移指南

在这个版本中,有 大量 的改进、错误修复和用户体验调整。以下是一些亮点:

  • 一个全新的现代渲染器,它更美观、更快,并且更易于扩展
  • 方向光和点光阴影
  • 集群前向渲染
  • 视锥剔除
  • 精灵渲染速度显著提升,代码更简洁
  • 原生 WebGL2 支持。你可以通过 在浏览器中运行 Bevy 示例 来测试它!
  • 高级自定义材质
  • 功能更强大的着色器:预处理器、导入、WGSL 支持
  • Bevy ECS 人体工程学和性能改进。不再有 .system()

继续阅读以了解更多详情!

新的 Bevy 渲染器 #

Bevy 0.6 引入了一个全新的现代渲染器,它

  • 更快:更多并行化、每个实体更少的计算、更有效的 CPU->GPU 数据流,以及(即将启用)流水线渲染
  • 更美观:我们与一些图形改进一起发布了新的渲染器,例如方向光和点光阴影、集群前向渲染(这样你就可以在一个场景中绘制更多灯光)以及球形区域光。我们还有大量正在开发的新功能(级联阴影贴图、泛光、粒子、阴影过滤器等等!)
  • 更简单:更少的抽象层、更简单的数据流、改进的低级、中级和高级接口、直接访问 wgpu
  • 模块化至其核心:标准化的 2D 和 3D 核心管道、可扩展的渲染阶段和视图、可组合的实体/组件驱动的绘制函数、着色器导入、通过 "子图" 实现可扩展和可重复的渲染管道
  • 行业验证:我们从经过实战检验的渲染器架构中汲取灵感,例如 Bungie 的流水线式 Destiny 渲染器。我们还从 Rust 空间中的其他渲染器开发人员那里学到了很多(并且与他们密切合作),包括 @aclysma (rafx) 和 @cwfitzgerald (rend3)。如果没有他们,新的 Bevy 渲染器不会是现在的样子,我强烈建议你查看他们的项目!

我保证我会在下面对所有这些模糊的术语进行说明。我相信新的 Bevy 渲染器将成为 Bevy 图形生态系统(希望也是整个 Rust 图形生态系统)的集结点。我们还有 大量 工作要做,但我为我们迄今为止取得的成就感到自豪,并且对未来感到兴奋!

bistro day

为什么构建一个新的渲染器? #

在我们介绍新功能之前,值得讨论一下我们为什么开始进行如此大规模的努力。旧的 Bevy 渲染器在很多方面做得很好

  • 模块化的渲染逻辑(通过渲染图)
  • 多个后端(第一方和第三方)
  • 高级数据驱动 API:这使得编写自定义的每个实体渲染逻辑变得容易和符合人体工程学

但是,它也有一些 严重的 缺陷

  • 复杂:"高级易用性"是以显著的实现复杂性、性能开销和发明术语为代价的。用户在尝试使用除 "高级" 以外的任何级别进行操作时,往往会感到不知所措。在管理 "渲染资源" 时,很容易做错事,也很难判断 "哪里出错了"。
  • 经常很慢:像 "精灵渲染" 这样的功能是基于上面提到的昂贵的高级抽象构建的。与生态系统中的其他选项相比,性能... 处于次优水平。
  • 面向用户的内部细节:它在每个实体上直接存储了大量的内部渲染状态。这会占用空间,计算状态很昂贵,并且会用一堆 "不要触碰" 的渲染组件来破坏面向用户的 API。这种状态(或者至少是组件元数据)需要写入/读取场景,这也很不理想,而且容易出错。
  • 重复的渲染逻辑很麻烦:视口、渲染到多个纹理/窗口以及阴影贴图都是可行的,但它们需要硬编码、特殊情况处理和样板代码。这与我们对模块化和清晰度的目标不一致。

为什么现在? #

上面的缺点在 Bevy 的早期阶段是可以接受的,但随着 Bevy 从一个 一个人的个人项目 发展成为 GitHub 上最流行的 Rust 游戏引擎(也是最流行的 流行的开源游戏引擎... 整个时期),这些缺点显然阻碍了我们前进。当我们有数百名贡献者、一名全职付费开发人员、数千名个人用户以及越来越多的公司为 Bevy 应用和功能支付人员时,"勉强可以接受" 的渲染器不再够用。是时候改变了。

有关我们决策和开发过程的更深入的见解(包括我们考虑过的替代方案),请查看 新渲染器跟踪问题

流水线渲染:提取、准备、排队、渲染 #

作者:@cart

流水线渲染是新渲染器的基石。它实现了多个目标

  • 提高并行性:我们现在可以开始运行下一帧的主应用程序逻辑,同时渲染当前帧。考虑到渲染通常是一个瓶颈,当有很多应用程序工作要做时,这将是一个巨大的胜利。
  • 更清晰的数据流和结构:流水线需要在 "应用程序逻辑" 和 "渲染逻辑" 之间划清界限,并设定一个固定的同步点(我们称之为 "提取" 步骤)。这使得对数据流和所有权进行推理变得更容易。代码可以沿着这些思路进行组织,从而提高清晰度。

从高层次来看,传统的 "非流水线渲染" 如下所示

non-pipelined rendering

流水线渲染如下所示

pipelined rendering

好多了!

Bevy 应用现在被分为主应用程序,这是应用程序逻辑发生的地方,以及渲染应用程序,它拥有自己的独立 ECS 世界和调度。渲染应用程序包含以下 ECS 阶段,开发人员在组合新的渲染功能时,会将 ECS 系统添加到这些阶段

  • 提取:这是主世界和渲染世界之间的唯一同步点。相关的实体、组件和资源从主世界读取,并写入渲染世界中的对应实体、组件和资源。目标是使此步骤尽可能快,因为它是唯一不能并行运行的逻辑。一个好的经验法则是只提取渲染所需的最小数据量,例如,只考虑 "可见" 实体,并且只复制相关的组件。
  • 准备:提取的数据随后会被 "准备",方法是将其写入 GPU。这通常涉及写入 GPU 缓冲区和纹理,以及创建绑定组。
  • 排队:这将 "排队" 从 "准备" 的数据中获取的渲染作业。
  • 渲染:这将运行渲染图,该渲染图根据渲染世界中从提取、准备和排队步骤存储的结果生成实际的渲染命令。

因此,流水线渲染实际上看起来更像这样,下一个应用程序更新发生在提取步骤之后

pipelined rendering stages

快速说明一下,流水线渲染目前还没有真正实现并行。我 有一个分支 启用了并行流水线,但目前在单独线程中运行应用程序逻辑会破坏“非发送”资源(因为主应用程序被移动到单独线程,破坏了非发送保证)。很快就会有修复程序,我只是想尽快将新渲染器送到大家手中!当我们启用并行流水线时,不需要任何用户界面代码更改。

渲染图和子图 #

作者:@cart

render graph

新的 Bevy 渲染器有一个渲染图,就像旧的 Bevy 渲染器一样。渲染图是一种以模块化方式逻辑建模 GPU 命令构造的方式。图形节点将纹理和缓冲区(有时还有实体)等 GPU 资源传递给彼此,形成一个有向无环图。当一个图形节点运行时,它使用其图形输入和渲染世界来构建 GPU 命令列表。

该 API 最大的变化是我们现在支持子图,子图基本上是“命名空间”渲染图,可以从图中任何节点以任意输入运行。这使我们能够定义诸如“2d”和“3d”子图之类的元素,用户可以在其中插入自定义逻辑。这同时打开了两个大门

  • 能够重复渲染逻辑,但针对不同的视图(分屏、镜子、渲染到纹理、阴影贴图)。
  • 用户能够扩展这种重复的逻辑。

拥抱 wgpu #

作者:@cart

Bevy 一直使用 wgpu,这是一个原生 GPU 抽象层,支持大多数图形后端:Vulkan、Metal、DX12、OpenGL、WebGL2 和 WebGPU(以及正在开发中的 DX11 支持)。但旧渲染器将其隐藏在我们自己的硬件抽象层之后。实际上,这在很大程度上只是一个 wgpu API 的镜像。它使我们能够构建自己的图形后端,而不必打扰 wgpu 的团队,但实际上它创造了许多痛苦(由于是一个不完美的镜像)、开销(由于引入了动态 API 并需要对 GPU 资源集合进行全局互斥锁)和复杂性(bevy_render -> wgpu -> Vulkan)。作为回报,我们并没有获得太多实际的好处……只是稍微更多一点的自主权。

事实是,wgpu 已经完全占据了我们想要它占据的空间

  • 多个后端,目标是支持尽可能多的平台
  • 一个“基线”功能集,几乎在所有地方都能使用一致的 API
  • 一个“限制”和“功能”系统,使我们能够选择加入任意(有时是特定于后端的)功能,并检测这些功能何时可用。这在我们开始添加诸如光线追踪和 VR 支持之类的东西时将非常重要。
  • 一个现代 GPU API,但没有原始 Vulkan 的痛苦和复杂性。非常适合面向用户的 Bevy 渲染器扩展。

但是,最初有一些原因没有将其作为我们的“面向公众的 API”

  • 复杂性:wgpu 过去是建立在 gfx-hal 之上的(另一个由 wgpu 团队构建和管理的旧 GPU 抽象层)。这些在多个仓库中的多个抽象层使得对内部进行贡献和推理变得困难。此外,我有一个关于“在 Bevy API 中公开暴露的第三方依赖项”的规则:我们必须感到能够在需要时分叉和维护它们(例如:上游停止维护、愿景发生分歧等)。我对使用旧架构这样做并不十分舒服。
  • 许可证:wgpu 过去是在“版权”MPL 许可证下发布的,这引起了人们对与专有图形 API 集成的担忧(例如,像 Switch 这样的游戏机)。
  • WebGL2 支持:wgpu 过去没有 WebGL2 后端。Bevy 的旧渲染器有一个自定义的 WebGL2 后端,我们不愿意放弃对 Web 作为平台的支持。

几乎立即,在我们表达了这些担忧之后,@kvark 开始了 重新许可工作,将 wgpu 切换到 Rust 标准的双重 MIT/Apache-2.0 许可证。他们还删除了 gfx-hal,转而使用 更简单、更扁平的架构。不久之后,@zicklag 添加了 WebGL2 后端。解决了我的所有剩余顾虑后,我清楚地认识到 @kvark 的优先事项与我的优先事项一致,并且我可以相信他们会根据社区反馈进行调整。

新的 Bevy 渲染器放弃了我们旧的中间 GPU 抽象层,转而直接使用 wgpu 作为我们的“低级”GPU API。结果是更简单(更快)的架构,可以完全直接访问 wgpu。到目前为止,来自 Bevy 渲染器功能开发人员的反馈非常积极

Bevy 还更新为使用最新的 wgpu 版本:0.12

ECS 驱动的渲染 #

作者:@cart

新渲染器是我喜欢称之为“ECS 驱动”的

  • 正如我们之前所述,渲染世界是使用从主世界中提取的数据填充的。
  • 场景是从一个或多个视图渲染的,这些视图只是渲染世界中的实体,具有与该视图相关的组件。视图实体可以使用任意组件进行扩展,这使得使用自定义视图数据和逻辑来扩展渲染器变得容易。相机不是唯一的视图类型。视图可以由渲染应用程序针对任意概念进行定义,例如“阴影贴图视角”。
  • 视图可以具有零个或多个泛型 RenderPhase<T: PhaseItem> 组件,其中 T 定义了该阶段中渲染的“类型和范围”(例如:“主通道中的透明 3d 实体”)。从本质上讲,RenderPhase 是一个(可能排序的)实体列表,用于绘制。
  • 渲染阶段中的实体使用绘制函数进行绘制,这些绘制函数从渲染世界读取 ECS 数据并生成 GPU 命令。
  • 绘制函数可以(可选地)由模块化绘制命令组成。这些通常范围限定于特定操作,例如 SetStandardMaterialBindGroupDrawMeshSetItemPipeline 等。Bevy 提供了许多内置的绘制命令,用户也可以定义自己的绘制命令。
  • 渲染图节点通过迭代每个渲染阶段的实体并运行相应的绘制函数,将特定视图的渲染阶段转换为 GPU 命令。

如果这看起来很复杂……别担心!这些是我喜欢称之为“中级”渲染器 API 的东西。它们提供了必要的工具,使经验丰富的渲染功能开发人员能够相对轻松地构建模块化渲染插件。我们还提供了易于使用的更高级别的 API,例如材质,这些 API 涵盖了大多数“自定义着色器逻辑”用例。

Bevy 的核心流水线 #

作者:@cart、Rob Swain (@superdump)、@KirmesBude、@mockersf

新渲染器在默认情况下非常灵活且不强加意见。但是,过多的灵活性并不总是理想的。我们希望拥有一个丰富的 Bevy 渲染器插件生态系统,在该生态系统中,开发人员拥有足够的自由来实现他们想要的东西,同时最大限度地提高插件之间的兼容性。

新的 bevy_core_pipeline 板条箱是我们对这个问题的答案。它定义了一组“核心”视图/相机(2d 和 3d)、子图(ClearPass、MainPass2d、MainPass3d)和渲染阶段(Transparent2dOpaque3dAlphaMask3dTransparent3d)。这为渲染功能开发人员提供了构建的“共同基础”,同时保持彼此的兼容性。只要开发人员在这些约束范围内操作,他们就应该与更广泛的生态系统兼容。开发人员也可以在这些约束之外操作,但这也会增加他们不兼容的可能性。

Bevy 的内置渲染功能建立在核心流水线之上(例如:bevy_spritebevy_pbr)。核心流水线将继续扩展,包括标准化的“后期处理”效果栈。

材质 #

作者:@cart

新的渲染器结构使开发人员能够对实体的绘制方式进行细粒度控制。开发人员可以手动定义提取、准备和排队系统,以使用自定义或内置的 RenderPhases 中的任意渲染命令来绘制实体。但是,这种级别的控制需要了解渲染流水线的内部结构,并且涉及比大多数用户愿意容忍的更多样板代码。有时你只想将自定义材质着色器插入现有的流水线中!

新的 Material 特性使用户能够忽略细枝末节,转而使用更简单的接口:只需实现 Material 特性,并为你的类型添加一个 MaterialPlugin。新的 shader_material.rs 示例说明了这一点。

// register the plugin for a CustomMaterial
app.add_plugin(MaterialPlugin::<CustomMaterial>::default())

impl Material for CustomMaterial {
    // the vertex and fragment shaders are optional
    // they use a default "mesh pipeline shader" if they are not defined
    fn fragment_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> {
        Some(asset_server.load("shaders/custom_material.wgsl"))
    }

    fn bind_group_layout(render_device: &RenderDevice) -> BindGroupLayout {
        /* return bind group layout here */
    }

    fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup {
        /* return bind group here */
    }
}

还有一个 SpecializedMaterial 变体,它使我们能够使用自定义的每个实体键来“专门化”着色器和流水线。这种额外的灵活性并不总是需要的,但是当你需要它时,你会很高兴拥有它!例如,内置的 StandardMaterial 使用专门化来切换实体是否应该在着色器中接收光照。

我们还计划让 Material 变得更好

  • 绑定组推导:这应该减少将材质传递到 GPU 的样板代码。
  • 材质实例化:材质使我们能够将高级网格实例化实现为内置和自定义材质的简单配置项。

可见性和视锥体剔除 #

作者:Rob Swain (@superdump)

view frustum

绘制东西很昂贵!它需要将数据从 CPU 写入 GPU,构建绘制调用,并运行着色器。我们可以通过绘制相机无法看到的物体来节省大量时间。“视锥体剔除”是指排除位于相机“视锥体”边界之外的物体,以避免浪费工作来绘制它们。对于大型场景,这可能是每秒 60 帧流畅运行和陷入困境的停滞之间的区别。

Bevy 0.6 现在使用 3d 物体的轴对齐边界框自动执行视锥体剔除。我们也可能在未来的版本中为 2d 对象启用此功能,但那里的收益将不那么明显,因为由于新的批处理渲染,绘制精灵现在便宜得多。

方向阴影 #

作者:Rob Swain (@superdump)

方向光现在可以投射“方向阴影”,这些阴影是从无限远的光源投射的“太阳状”阴影。可以通过将 DirectionalLight::shadows_enabled 设置为 true 来启用它们。

directional light

注意:方向阴影目前需要比必要的更多手动配置(查看 shadow_projection 字段,位于 shadow_biases.rs 示例中的 DirectionalLight 设置中)。我们很快将通过级联阴影贴图使它变得自动化,并在更大范围内提高质量。

点光源阴影 #

作者:@mtsr、Rob Swain (@superdump)、@cart

点光源现在可以投射“全向阴影”,可以通过将 PointLight::shadows_enabled 设置为 true 来启用它们

point light

启用和禁用实体阴影 #

作者:Rob Swain (@superdump)

网格实体可以通过添加 NotShadowCaster 组件来选择不投射阴影。

commands.entity(entity).insert(NotShadowCaster);

同样,它们可以通过添加 NotShadowReceiver 组件来选择不接收阴影。

commands.entity(entity).insert(NotShadowReceiver);

球形区域光源 #

作者:@Josh015

PointLight 组件现在可以定义 radius 值,该值控制发射光的球体的尺寸。一个正常的零尺寸“点光源”的半径为零。

spherical area lights

(请注意,具有半径的灯光通常不会占用世界中的物理空间... 我添加了网格来帮助说明灯光的位置和大小)

可配置的 Alpha 混合模式 #

作者:Rob Swain (@superdump)

Bevy 的 StandardMaterial 现在有一个 alpha_mode 字段,它可以设置为 AlphaMode::OpaqueAlphaMode::Mask(f32)AlphaMode::Blend。 加载 GLTF 场景时,此字段将被正确设置。

alpha blend modes

聚簇前向渲染 #

作者:Rob Swain (@superdump)

现代场景通常有许多点光源。但是,在渲染场景时,为每个灯光计算每个渲染片段的照明,随着场景中灯光数量的增加,很快就会变得难以承受。 聚簇前向渲染 是一种流行的方法,它通过将视锥体划分为“聚簇”(一个 3D 子体积网格)来增加场景中可以拥有的灯光数量。每个聚簇都根据灯光是否可以影响该聚簇来分配灯光。这是一种“剔除”形式,它使片段能够忽略未分配给其聚簇的灯光。

在实践中,这可以显着增加场景中的灯光数量

clustered forward rendering

聚簇是视锥体的 3D 细分。它们是投影空间中的长方体,因此对于透视投影,它们在视图空间中被拉伸和扭曲。当在屏幕空间中调试它们时,您是在沿着聚簇的一行进行查看,因此它们看起来像正方形。正方形内的不同颜色代表网格表面位于场景中的不同深度,因此它们属于不同的聚簇

clusters

当前实现限制为最多 256 个灯光,因为我们最初优先考虑跨平台兼容性,以便每个人都能从中受益。WebGL2 特别不支持存储缓冲区,因此当前实现受到最大统一缓冲区大小的限制。我们可以通过使用存储缓冲区在其他平台上支持更多灯光,我们将在未来的版本中添加对存储缓冲区的支持。

点击这里 查看演示 Bevy 聚簇前向渲染的视频。

精灵批处理 #

作者:@cart

精灵现在根据其纹理在 z 级内进行批处理渲染。它们还可以在 z 级之间进行机会批处理。这带来了显著的性能提升,因为它大幅减少了所需的绘制调用次数。将此与新 Bevy 渲染器中的其他性能改进相结合,事情开始变得非常有趣!在我的机器上,旧的 Bevy 渲染器在我们的“bevymark”基准测试中大约 8,000 个精灵时通常开始下降到 60fps 以下。使用同一台机器上的新渲染器,我可以获得大约 100,000 个精灵!

bevymark

我的机器:Nvidia GTX 1070、Intel i7 7700k、16GB 内存、Arch Linux

精灵人体工程学 #

精灵实体现在更容易生成

fn spawn_sprite(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn_bundle(SpriteBundle {
        texture: asset_server.load("player.png"),
        ..Default::default()
    });
}

无需管理精灵材质!它们的纹理句柄现在是直接组件,颜色现在可以直接在 Sprite 组件上设置。

为了比较,请展开此内容以查看旧的 Bevy 0.5 代码
// Old (Bevy 0.5)
fn spawn_sprite(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    let texture_handle = asset_server.load("player.png");
    commands.spawn_bundle(SpriteBundle {
        material: materials.add(texture_handle.into()),
        ..Default::default()
    });
}

WGSL 着色器 #

Bevy 现在使用 WGSL 用于我们的内置着色器和示例。WGSL 是一种为 WebGPU 开发的新着色器语言(尽管它是一种“跨平台”着色器语言,就像 GLSL 一样)。Bevy 仍然支持 GLSL 着色器,但 WGSL 足够好,所以目前我们将其视为我们的“正式推荐”着色器语言。WGSL 仍在开发和完善中,但鉴于它收到的投资额,我相信它值得押注。请将此视为“正式的 Bevy 着色器语言”对话的开始,而不是结束。

[[group(0), binding(0)]]
var<uniform> view: View;

[[group(1), binding(0)]]
var<uniform> mesh: Mesh;

struct Vertex {
    [[location(0)]] position: vec3<f32>;
};

struct VertexOutput {
    [[builtin(position)]] clip_position: vec4<f32>;
};

[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;
    out.clip_position = view.view_proj * mesh.model * vec4<f32>(vertex.position, 1.0);
    return out;
}

着色器预处理器 #

作者:@cart、Rob Swain (@superdump)、@mockersf

Bevy 现在拥有自己的自定义着色器预处理器。它目前支持 #import#ifdef FOO#ifndef FOO#else#endif,但我们将扩展它以提供更多功能,以实现简单、灵活的着色器代码重用和扩展。

着色器预处理器通常用于有条件地启用着色器代码

#ifdef TEXTURE
[[group(1), binding(0)]]
var sprite_texture: texture_2d<f32>;
#endif

这种模式在定义复杂/可配置的着色器(例如 Bevy 的 PBR 着色器)时非常有用。

着色器导入 #

作者:@cart

新的预处理器支持导入其他着色器文件(这将引入其全部内容)。它有两种形式

资产路径导入

#import "shaders/cool_function.wgsl"

[[stage(fragment)]]
fn fragment(input: VertexOutput) -> [[location(0)]] vec4<f32> {
    return cool_function();
}

插件提供的导入,可以由 Bevy 插件使用任意路径注册

#import bevy_pbr::mesh_view_bind_group

[[stage(vertex)]]
fn vertex(vertex: Vertex) -> VertexOutput {
    let world_position = vec4<f32>(vertex.position, 1.0);
    var out: VertexOutput;
    // The `view` variable comes from the imported bind group 
    out.clip_position = view.view_proj * world_position;
    return out;
}

我们还计划尝试使用 Naga 进行特定命名符号的“部分导入”(例如:从文件中导入特定函数或结构)。这是一个“遥远的”想法,但这也可以使使用 Naga 的中间着色器表示成为一种方法,将以不同语言编写的着色器代码片段组合成一个着色器。

管道专门化 #

作者:@cart

当着色器使用预处理器并具有多个排列时,关联的“渲染管道”需要进行更新以适应这些排列(例如:不同的顶点属性、绑定组等)。为了使此过程变得简单,我们添加了 SpecializedPipeline 特性,它允许为给定的键定义专门化

impl SpecializedPipeline for MyPipeline {
    type Key = MyPipelineKey;
    // The key here is specified for entities when queuing them up in a RenderPhase
    fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
        // define a specialized pipeline for the given key here
    }
}

此特性的实现者可以轻松且廉价地访问专门的管道变体(具有自动的每键缓存和热重载)。如果这感觉太抽象/太高级,请不要担心!这是一个“中级高级用户工具”,而不是大多数 Bevy App 开发人员需要处理的东西。

更简单的着色器堆栈 #

Bevy 现在使用 Naga 来满足其所有着色器需求。因此,我们能够删除所有复杂的非 Rust 着色器依赖项:glsl_to_spirvshadercspirv_reflectglsl_to_spirv 是平台特定构建依赖项和错误的主要制造商,因此这是一个巨大的胜利!

移植到新渲染器的功能 #

在许多情况下,内部 Bevy 箱的渲染逻辑必须重写以利用新渲染器。以下人员帮助完成了这项工作

  • bevy_sprites:@cart、@StarArawn、@Davier
  • bevy_pbr:Rob Swain (@superdump)、@aevyrie、@cart、@zicklag、@jakobhellermann
  • bevy_ui:@Davier
  • bevy_text:@Davier
  • bevy_gltf:Rob Swain (@superdump)

WebGL2 支持 #

作者:@zicklag、@mrk-its、@mockersf、Rob Swain (@superdump)

Bevy 现在内置支持使用 WebGL2/WASM 部署到 Web,这得益于 @zicklag 为 wgpu 添加了本机 WebGL2 后端。现在无需第三方 bevy_webgl2 插件。任何 Bevy 应用程序都可以通过运行以下命令部署到 Web

cargo build --target wasm32-unknown-unknown
wasm-bindgen --out-dir OUTPUT_DIR --target web TARGET_DIR

新 Bevy 渲染器开发人员优先考虑初始渲染器功能实现的跨平台兼容性,因此必须谨慎地在 WebGL2 的限制内操作(例如:存储缓冲区和计算着色器在 WebGL2 中不受支持),但结果是值得的!随着时间的推移,将实现利用更现代/更高级功能(例如计算着色器)的功能。但对我们来说重要的是,无论目标平台如何,每个人都能获得其游戏和应用程序的可靠视觉体验。

您可以在浏览器中使用我们新的 Bevy 示例 页面试用 Bevy 的 WASM 支持

wasm bevy examples

无限反向 Z 透视投影 #

作者:Rob Swain (@superdump)

为了提高“有用范围”内的精度,该行业已广泛采用具有“无限”远平面的“反向投影”。新的 Bevy 渲染器已改编为使用“右手无限反向 z”投影。 这篇文章 对为什么这非常值得解释得很好。

计算着色器 #

新的渲染器使用户能够编写计算着色器。我们的新 “计算着色器生命游戏”示例(作者:@jakobhellermann)演示了如何在 Bevy 中编写计算着色器。

compute game of life

新的多个窗口示例 #

作者:@DJMcNab

“多个窗口”示例已更新为使用新的渲染器 API。由于新的渲染器 API,此示例现在 看起来要好得多(当我们添加高级渲染目标时,它会看起来更好)。

multiple windows

Crevice #

作者:@cart、@mockersf、Rob Swain (@superdump)

Bevy 的旧 Bytes 抽象已被 crevice 箱(作者:@LPGhatguy)的分支取代,这使得将普通 Rust 类型写入 GPU 友好的数据布局成为可能。即 std140(统一缓冲区默认为此布局)和 std430(存储缓冲区默认为此布局)。Bevy 导出 AsStd140AsStd430 派生

#[derive(AsStd140)]
pub struct MeshUniform {
    pub transform: Mat4,
    pub inverse_transpose_model: Mat4,
}

AsStd140 派生与我们新的 UniformVec<T> 类型相结合,可以轻松地将 Rust 类型写入着色器就绪的统一缓冲区

// WGSL shader
struct Mesh {
    model: mat4x4<f32>;
    inverse_transpose_model: mat4x4<f32>;
};

[[group(2), binding(0)]]
var<uniform> mesh: Mesh;

我们(短期内)分叉 crevice 的原因有以下几个

  • 为了合并由 @ElectronicRU 提出的 数组支持 PR,因为我们需要在我们的统一变量中支持数组。
  • 重新导出 crevice 派生并为 Bevy 提供“开箱即用”的体验

最终,我们希望尽可能地向上游迁移。非常感谢 crevice 开发人员构建如此有用的软件!

UV 球体网格形状 #

作者:@nside

Bevy 现在有一个内置的“uv 球体”网格图元。

Mesh::from(UVSphere {
    radius: 1.0,
    sectors: 16,
    stacks: 32,
})

uv sphere

平面法线计算 #

作者:@jakobhellermann

Mesh 类型现在有一个 compute_flat_normals() 函数。没有法线的导入 GLTF 网格现在会自动计算平面法线,符合 GLTF 规范

flat normals

更快的 GLTF 加载 #

作者:@DJMcNab、@mockersf

@DJMcNab 修复了 GLTF 节点的令人讨厌的非线性加载,这使得它们加载速度快得多。一个复杂的场景从 40 秒缩短到 0.2 秒。太棒了!

@mockersf 使 GLTF 纹理在 Bevy 的“IO 任务池”中异步加载,这在某些情况下几乎将 GLTF 场景加载时间减少了一半。

我们还在添加“压缩纹理加载”的过程中,这将大幅加快 GLTF 场景加载速度,尤其是对于大型场景!

Bevy ECS #

不再有 .system()#

作者:@DJMcNab、@Ratysz

我们对 Bevy ECS 的最高优先事项之一是“人体工程学”。过去,我已经大胆声称 Bevy ECS 是 现存最具人体工程学特性的 ECS。我们在开创新的 API 技术方面投入了大量资金,我相信结果不言而喻

// This is a standalone Bevy 0.5 App that adds a simple `gravity` system to the App's schedule
// and automatically runs it in parallel with other systems
fn main() {
    App::build()
        .add_plugins(DefaultPlugins)
        .add_system(gravity.system())
        .run();
}

fn gravity(time: Res<Time>, mut query: Query<&mut Transform>) {
    for mut transform in query.iter_mut() {
        transform.translation.y += -9.8 * time.delta_seconds();
    }
}

我认为我们已经远远领先于市场(尤其是如果您考虑到我们的自动并行化和更改检测),但有一件事阻碍了我们走向完美... 讨厌的 .system()!我们已经多次尝试将其删除,但由于 rustc 限制和安全问题,它一直困扰着我们。最终,@DJMcNab 找到了解决方案。因此,在 Bevy 0.6 中,您现在可以像这样注册上面的系统

// pure bliss!
App::new()
    .add_plugins(DefaultPlugins)
    .add_system(gravity)
    .run();

新的 Component 特性和 #[derive(Component)] #

作者:@Frizi

Bevy 0.6中,类型不再默认实现Component trait。在你生气之前...请先听我说一下。我保证这是最好的选择!在之前的Bevy版本中,我们通过使用这种“blanket impl”来“自动实现”Component trait。

impl<T: Send + Sync + 'static> Component for T {}

这样就无需用户手动为他们的类型实现Component。在早期,这似乎是一个没有缺点的简化操作。但Bevy ECS、我们对问题空间的理解以及我们对未来的计划,自那时起已经发生了很大变化。

  • 事实证明,并非所有东西都应该是Component:我们的用户经常无意中将非组件类型添加为组件。新用户无意中将Bundle和类型构造函数添加为Component,是我们在Discord上最常见的#help频道帖子。这类错误很难调试,因为它们只是默默地“不起作用”。当并非所有东西都是Component时,rustc可以正确地用信息性错误提醒你,当你出错时。
  • 优化:如果我们自动为所有东西实现Component,我们就无法使用关联类型来定制Component trait。这将阻止一类完整的优化。例如,Bevy ECS现在拥有多种Component存储类型。通过将存储类型移到Component中,我们使rustc能够优化原本需要在运行时执行的检查。@Frizi能够显著提升我们的Query迭代器性能,通过将存储类型移到Component中。我希望我们能在这类优化方面取得更多进展。
  • 自动注册:将更多逻辑移到Component中,也使我们能够在未来做一些更复杂的事情,比如“在派生Component时自动注册Reflect实现”。非blanketComponent实现确实会增加一些样板代码,但它们也可能大幅减少应用程序的“总样板代码”。
  • 文档:派生Component是一种自我文档的形式。现在很容易一眼就看出哪些类型是组件。
  • 组织:在Bevy 0.5中,Component特定的配置,比如“存储类型”,必须注册在某个中心化的插件中。将Component配置移到Component trait中,允许用户将“Component类型信息”直接保存在类型本身旁边。
  • 事件处理程序:非blanketComponent实现最终将允许我们在Component trait中添加事件处理程序,比如on_insert(world: &mut World)。非常有用!

希望你现在已经相信这是正确的选择。如果没有...我很抱歉...你仍然需要在Bevy 0.6中手动实现Component。你可以派生Component

// defaults to "Table" storage
#[derive(Component)]
struct SomeComponent;

// overrides the default storage
#[derive(Component)]
#[component(storage = "SparseSet")]
struct SomeComponent;

或者你可以手动实现它。

struct SomeComponent;

impl Component for SomeComponent {
    type Storage = TableStorage;
}

impl Component for SomeComponent {
    type Storage = SparseSetStorage;
}

可变查询的iter() #

作者:@Guvante

现在可以不可变地迭代可变查询,返回组件的不可变引用。

fn system(mut players: Query<&mut Player>) {
    for player in players.iter() {
        // player is an immutable reference
    }

    for mut player in players.iter_mut() {
        // player is a mutable reference
    }
}

将其与之前的Bevy版本中为了避免不可变和可变查询冲突而需要的复杂QuerySet进行比较。

// Gross!
fn system(mut players: QuerySet<(QueryState<&Player>, QueryState<&mut Player>)>) {
    for player in players.q0().iter() {
        // player is an immutable reference
    }

    for mut player in players.q1().iter_mut() {
        // player is a mutable reference
    }
}

SystemState #

你是否曾经想直接使用“系统参数”与Bevy World进行交互?有了SystemState,现在你可以做到!

let mut system_state: SystemState<(Res<A>, Query<&B>)> = SystemState::new(&mut world);
let (a, query) = system_state.get(&world);

对于那些直接使用World的人来说,这是一个改变游戏规则的功能。它使你可以可变地访问多个不相交的Component和Resource(通常消除了对更昂贵的抽象(比如WorldCell)的需求)。

SystemState执行与普通Bevy系统相同的缓存操作,因此重复使用同一个SystemState可以实现超快的World访问。

子应用程序 #

作者:@cart、@zicklag、@bjorn3

新的Bevy渲染器要求“主应用程序”和“渲染应用程序”之间严格分离。为了实现这一点,我们添加了“子应用程序”的概念。

#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, AppLabel)]
pub struct RenderApp;

let mut render_app = App::empty();
app.add_sub_app(RenderApp, render_app, move |app_world, render_app| {
    // execute app logic here
});

// later
app.sub_app_mut(RenderApp)
    .add_system(some_system);
    .add_system(some_other_system);

我们计划在未来提供更多对子应用程序的调度、运行和交互的控制。

Query::iter_combinations #

作者:@Frizi

你现在可以迭代给定查询的N个实体的所有组合。

fn system(query: Query<&Player>) {
    // iterates each possible combination of two entities exactly once
    for [p1, p2] in query.iter_combinations() {
    }

    // iterates each possible combination of three entities exactly once
    for [p1, p2, p3] in query.iter_combinations() {
    }
}

这对于“检查与所有其他实体发生碰撞的实体”等操作特别有用。还有一个iter_combinations_mut变体。注意...当组合中的实体数量增加时,此操作的时间复杂度呈指数级增长。能力越大,责任越大!

新的iter_combinations示例演示了如何使用此新API来计算“太阳系”中物体之间的重力。

iter_combinations

优化后的系统命令 #

作者:@NathanSWard

通过改变命令缓冲区的存储和重用方式,系统命令获得了显著的性能提升。

实体生成基准测试持续时间(以微秒为单位,越低越好) #

此基准测试生成具有各种组件组合的实体,以确保我们覆盖各种情况。将这些数字视为相对值,而不是绝对值。

commands perf

系统参数生命周期 #

作者:@cart、@BoxyUwU、@TheRawMeatball

通过将'system'world生命周期分开,并尽可能显式地使用它们,系统和查询生命周期变得更加明确。这使Rust能够更有效地推断ECS生命周期,特别是对于只读生命周期。这非常重要,因为它使新的Bevy渲染器能够说服wgpu,ECS资源实际上可以持续到Render World的生命周期。

注意,这确实使得SystemParam派生的生命周期略微复杂。

#[derive(SystemParam)]
struct CustomParam<'w, 's> {
    res: Res<'w, AssetServer>,
    query: Query<'w, 's, Read<Transform>>,
    local: Local<'s, i32>,
}

健壮性/正确性改进 #

作者:@BoxyUwU、@TheRawMeatball、@Frizi、@thebluefish、@sapir、@bjorn3、@DJMcNab

Bevy ECS在此版本中进行了大量的健壮性和正确性错误修复,还删除了一些不安全的代码块。查询和内部存储(比如Table和BlobVec)在这些方面进行了大量修复和改进。随着Bevy ECS的成熟,我们对不安全代码块和健壮性的要求也必须提高。Bevy ECS可能永远无法完全摆脱不安全的代码块,因为我们正在模拟Rust无法在没有我们帮助的情况下推断的并行数据访问。但我们致力于尽可能地移除不安全的代码(我们正在进行一些重构,以进一步改善这种情况)。

层次结构便利函数 #

作者:@TheRawMeatball、@jihiggins
// Despawns all descendants of an entity (its children, its childrens' children, etc)
commands.entity(e).despawn_descendants();

// Removes the given children from the entity
commands.entity(parent).remove_children(&[child1, child2]);

UI #

Overflow::Hidden #

作者:@Davier

UI现在尊重flexbox Overflow::Hidden属性。这可以用来截断子内容,在构建可滚动列表等功能时很有用。

overflow hidden

Text2D变换 #

作者:@nside、@CleanCut

Text2d现在支持使用Transform组件进行任意变换。

text 2d transforms

注意,虽然Transform::scale确实有其用途,但通常仍然建议使用“字体大小”来调整文本大小,以确保其“清晰”渲染。

窗口透明度 #

作者:@louisgjohnson

Winit的“窗口透明度”功能现在已在Bevy的Window类型中公开。这允许用户构建没有背景或窗口装饰的“小部件式”应用程序(在支持此功能的平台上)。这是一个具有透明背景的Bevy应用程序,在Linux桌面背景之上渲染一个Bevy Logo精灵。无缝衔接!很酷!

transparent window

变换 #

友好的方向向量 #

作者:@guimcaballero

Bevy变换现在具有友好的“方向”函数,可以返回相对向量。

// Points to the left of the transform
let left: Vec4 = transform.left();
// Points to the right of the transform
let right: Vec4 = transform.right();
// Points up from the transform
let up: Vec4 = transform.up();
// Points down from the transform
let down: Vec4 = transform.down();
// Points forward from the transform
let forward: Vec4 = transform.forward();
// Points back from the transform
let back: Vec4 = transform.back();

变换构建器方法 #

作者:@Lythenas

变换现在具有有用的with_translation()with_rotation()with_scale()构建器方法。

Transform::from_xyz(0.0, 0.0, 10.0).with_scale(Vec3::splat(2.0))

Rust 2021 #

作者:@mockersf、@YohDeadfall

Bevy已更新为使用Rust 2021。这意味着我们可以默认利用新的Cargo功能解析器(Bevy和新的wgpu版本都需要它)。确保将你的Crates更新到Rust 2021,否则你需要在你的Cargo.toml中使用resolver = "2"手动启用新的功能解析器。

[package]
name = "your_app"
version = "0.1.0"
edition = "2021"

注意,“虚拟Cargo工作区”仍然需要手动定义resolver = "2",即使在Rust 2021中也是如此。参阅Rust 2021文档了解详细信息。

[workspace]
resolver = "2" # Important! wgpu/Bevy needs this!
members = [ "my_crate1", "my_crate2" ]

输入 #

游戏手柄资源 #

作者:@CrazyRoka

Bevy 0.6添加了一个Gamepads资源,它会自动维护已连接的游戏手柄的集合。

fn system(gamepads: Res<Gamepads>) {
    // iterates every active game pad
    for gamepad in gamepads.iter() {
    }
}

输入“任何”变体 #

作者:@DJMcNab

Input集合现在具有一个any_pressed()函数,当给定的任何输入被按下时,它会返回true。

 fn system(input: Res<Input<KeyCode>>) {
    if input.any_pressed([KeyCode::LShift, KeyCode::RShift]) {
        println!("one or both of the two shift keys are pressed");
    }
 }

分析 #

更多跨度 #

作者:@cart、@mockersf、@hymm

新的渲染器现在具有帧、渲染应用程序调度和渲染图(带有命名子图跨度)的跟踪跨度。系统执行器现在具有更细粒度的跨度,填补了大部分剩余空白。应用系统命令现在也具有跨度。

(忽略跨度中那些奇怪的字符...我们正在调查此事)

render app profiling

Tracy后端 #

作者:Rob Swain (@superdump)

Bevy现在通过trace_tracy Cargo功能支持tracy分析器。

tracy

FromReflect Trait和派生 #

作者:@Davier

类型现在可以派生新的FromReflect trait,这使得可以使用任意Reflect实现来创建类型的“克隆”。这目前用于使反射集合类型(比如Vec)正常工作,但它也适用于与Reflect类型之间的“往返”转换。

#[derive(Reflect, FromReflect)]
struct Foo {
    bar: usize,
}

let foo = Foo::from_reflect(&dyn some_reflected_value).unwrap(); 

Bevy错误代码 #

作者:@mockersf、@NiklasEi

为了便于搜索和讨论常见的Bevy错误,我们决定添加一个正式的错误代码系统,类似于rustc使用的系统

错误代码及其描述也具有一个自动生成的Bevy网站页面

Bevy资产 #

作者:@mockersf

包含 Bevy 插件、crates、应用程序和学习资源列表的 curated awesome-bevy GitHub 仓库现已重生为 Bevy Assets

Bevy Assets 引入了

这仅仅是个开始!我们计划与 crates.io 和 GitHub 集成,改进索引/标签/可搜索性,添加特定于资产的页面,更漂亮的样式,内容交付等等。最终,我们希望将其发展成为能够支持一流的、现代的资产驱动工作流的东西。

我们已自动迁移现有的 awesome-bevy 条目,但我们鼓励创建者对其进行自定义!如果您正在进行与 Bevy 相关的项目,我们强烈建议您 添加 Bevy Assets 条目

双 MIT/Apache-2.0 许可证 #

作者:@cart,@DJMcNab

感谢相关贡献者(总计 246 位),Bevy 现在在 MIT 和 Apache-2.0 许可下双重授权,由开发者选择。这意味着开发者可以选择最适合其特定需求的许可证。我想强调,这比仅限 MIT 的授权方式 *更少* 限制,而不是更多。

我最初选择在 MIT 许可下独家授权 Bevy,出于多种原因

  • 人们和公司通常比其他任何许可证更了解并信任 MIT 许可证。Apache 2.0 并不那么知名和可信。
  • 它简短易懂
  • 许多人不熟悉 "多个许可证选项......选择您最喜欢的" 方式。我不想不必要地吓跑人们。
  • 像 Godot 这样的其他开源引擎在仅限 MIT 的授权方式下取得了很大成功

然而,出现了一些问题,使得在 MIT 和 Apache-2.0 许可下对 Bevy 进行双重授权变得很有吸引力

  • MIT 许可证(可以说是)要求二进制文件为每个使用的 MIT 库复制无数个相同许可证说明。Apache-2.0 允许我们将说明压缩到单个许可证实例中。
  • Apache-2.0 许可证包含对专利流氓的保护和明确的贡献许可条款。
  • Rust 生态系统很大程度上是 Apache-2.0。在该许可证下可用有利于互操作性,并为将 Bevy 代码上游到其他项目(Rust、异步生态系统等)打开了大门。
  • Apache 许可证与 GPLv2 不兼容,但 MIT 兼容。

Bevy 组织变更 #

更多拉取请求合并! #

我已经处于可扩展性的极限一段时间了。*咳咳*......要构建我需要的引擎功能,快速审核每一个拉取请求,并保持我的心理健康,这确实很 *具有挑战性*。我一直坚持到现在......有时通过过度工作,有时通过让 PR 比我想象的时间更长地保持未合并状态。通过扩展,我们可以鱼与熊掌兼得!

  • @mockersf 现在拥有对 "非争议性更改" 的合并权限
  • @alice-i-cecile 现在拥有对 "非争议性文档更改" 的合并权限

新的问题标签 #

经过 关于命名约定和颜色的很多讨论,我们终于有了 一套全新的问题标签(松散地受到 rust 仓库的启发)。Bevy Triage 团队 终于可以充分表达自己了!

全面的 CONTRIBUTING.md #

作者:@alice-i-cecile

我们现在有一个相对完整的 贡献者指南。如果您有兴趣为 Bevy 贡献代码或文档,这是一个很好的起点!

CI 构建系统改进 #

作者:@mockersf,@NathanSWard,@NiklasEi

我们在本版本中进行了大量的 CI 改进

  • 我们现在会在 cargo doc 警告时失败
  • 我们现在使用 cargo deny 来防止漏洞、重复依赖项和无效许可证
  • PR 现在会自动加上 S-Needs-Triage 标签
  • CI 稳定性和速度改进
  • 我们现在检查我们的基准测试是否构建成功
  • 我们现在断言 compile_fail 测试的编译器错误,为我们提供了更严格的保证
  • 示例现在使用 lavapipe(而不是 swiftshader)运行,以实现更快的 CI 验证

Bevy 的下一步计划? #

Bevy 的开发继续加速,我们现在没有放缓的打算!除了我们正在进行的 许多 RFC 之外,我们还计划在未来几个月内解决以下问题

"火车" 发布计划 #

在过去的两个 Bevy 版本中,我们对核心系统进行了巨大的、全面的更改。**Bevy 0.5** 是 "我们重写 Bevy ECS 的版本"。**Bevy 0.6** 是 "我们重写 Bevy Render 的版本"。这些巨大的重写工作需要时间,因此阻碍了许多其他有用的功能和错误修复。它们还造成了 "加班赶工" 和快速完成大型功能以解除发布阻碍的压力。加班赶工是不健康的,应该不惜一切代价避免!

Bevy 社区 达成了相对共识,认为我们应该有一个更规律、更可预测的发布计划。在这个计划中,大型功能不会阻塞系统。

从现在开始,我们将 *大约* 每三个月发布一次(作为上限......如果合理,有时我们可能会提前发布)。在发布周期结束之后,我们将开始准备进行发布。如果需要进行一些小调整或 "发生了一些事情"......我们会很乐意推迟发布。但是,我们不会再为了 "大项目" 而推迟发布。

我们正在平衡许多不同的担忧

  • 让 Bevy 贡献者相信他们的更改会及时发布
  • 让 Bevy 用户相信他们会收到定期更新和错误修复
  • 在发布之间留出足够的时间,以减少 Bevy 插件生态系统的 churn(Bevy 还没有 "稳定",但更长的发布周期提供了 "生态系统稳定性" 的合理窗口)
  • 在发布中提供足够的内容以产生 "炒作"。Bevy 发布博客文章往往是社区的 "号召令",我不想失去这一点。
  • 为核心开发人员建立适当的工作/生活平衡(加班赶工是糟糕的!)

我们将随着时间的推移完善这个过程,并找到最有效的方法。

更多渲染器功能 #

  • **后期处理堆栈/HDR/光晕**:HDR 和光晕 几乎进入了 Bevy 0.6,但我们决定将其推迟,以便我们可以对其进行一些完善,并构建一个适当的 "模块化后期处理堆栈"。
  • **骨骼动画**:最终,Bevy 将拥有一个通用的、基于属性的动画系统(我们已经有了 工作实现)。我们一直在推迟添加骨骼动画,以便将其添加到该系统中,但回顾起来这是一个错误。人们 *现在* 需要骨骼动画。在短期内,我们将构建一个范围有限的 3D 骨骼动画系统,只是为了让事情开始运转。然后,我们将在以后将其移植到通用系统中(无论何时准备好),
  • **屏幕空间环境光遮蔽 (SSAO)**:一种流行且直接的环境光遮蔽近似方法,可以大幅提升渲染质量。
  • **全局照明**:GI 将极大地提升 "真实感",因此值得在短期内优先考虑至少一种形式的 GI。这是一个复杂的话题,需要进行实验。
  • **压缩纹理**:这将使场景加载速度更快,并减少 GPU 内存使用量。
  • **阴影过滤器和级联**:Rob Swain (@superdump) 已经在该领域做了很多工作,因此我们希望很快就能在 Bevy 版本中看到它的实现。
  • **PBR 着色器代码重用**:我们将通过使 PBR 着色器更加模块化,并更轻松地导入 PBR 着色器的特定部分,来简化自定义 PBR 着色器的定义。

UI 刷新 #

我们将在今年开始开发 Bevy 编辑器。为此,我们需要对 Bevy UI 进行一些改进

  • 改进的 "数据驱动 UI"(可能是 "反应式")
  • 一套可靠的预构建小部件
  • 总体上改进的 UX

我们现在在 Bevy 社区中进行大量 UI 实验。在未来几个月内,我们将细化我们的范围,并开始 "选择赢家" 的过程。

资产预处理 #

预处理资产是生产游戏引擎的关键部分。它减少了启动时间,减少了 CPU 和 GPU 内存占用,支持更复杂开发工作流,简化了游戏资产的发布,并减少了已部署游戏的最终大小。我们一直没有资产预处理系统......但差一点。尽快解决这个问题对我来说是重中之重。

场景改进 #

嵌套场景、属性覆盖、内联资产和更友好的语法都在日程表上。我们已经在这些领域进行了一些工作实验,因此应该会看到相对快速的进展。

新的 Bevy 书籍 #

目前的 Bevy 书籍是学习如何设置 Bevy 并开始编写 Bevy 应用程序的绝佳方式。但它只是触及了 Bevy 能力的皮毛。

为了解决这个问题,@alice-i-cecile 已开始着手编写一本新的 Bevy 书籍,目标是成为 Bevy 的完整学习资源。如果您有兴趣帮忙,请联系他们!

Bevy 月度通讯 #

Bevy 社区 是一个充满活力和积极的场所。目前,大多数社区内容都发布在 Bevy Discord#showcase 部分中。即将发布的 Bevy 月度通讯将是一个整合的、可共享的资源,我们将将其发布到 Reddit 和 Twitter 等地方。

支持 Bevy #

赞助有助于使我全职开发 Bevy 变得可持续。如果您相信 Bevy 的使命,请考虑赞助我 (@cart)......每一分钱都有帮助!

捐赠 心形图标

贡献者 #

衷心感谢**170 位贡献者**使本版本(以及相关文档)成为可能!随机顺序

  • @bilsen
  • @jcornaz
  • @Guvante
  • @Weasy666
  • @jakobhellermann
  • @gfreezy
  • @MichaelHills
  • @tcmal
  • @temhotaokeaha
  • @nicopap
  • @dimitribobkov
  • @Newbytee
  • @TheRawMeatball
  • @marcospb19
  • @MarenFayre
  • @jleflang
  • @piedoom
  • @FlyingRatBull
  • @thomasheartman
  • @dburrows0
  • @squidboylan
  • @GarettCooper
  • @nside
  • @deprilula28
  • @Jbat1Jumper
  • @HackerFoo
  • @MatheusRich
  • @inodentry
  • @cryscan
  • @aleksator
  • @Toqozz
  • @concave-sphere
  • @jesseviikari
  • @dependabot
  • @zicklag
  • @mnett82
  • @guimcaballero
  • @lukors
  • @alice-i-cecile
  • @fintelia
  • @BoxyUwU
  • @gcoakes
  • @folke
  • @iwikal
  • @tsoutsman
  • @phrohdoh
  • @julhe
  • @Byteron
  • @TehPers
  • @andoco
  • @djeedai
  • @branan
  • @follower
  • @MiniaczQ
  • @terrarier2111
  • @joshuataylor
  • @CleanCut
  • @akiross
  • @rukai
  • @PaperCow
  • @CGMossa
  • @Josh015
  • @gschup
  • @james7132
  • @MyIsaak
  • @Hoidigan
  • @mccludav
  • @mnmaita
  • @sapir
  • @gilescope
  • @VVishion
  • @sarkahn
  • @fractaloop
  • @KDecay
  • @aloucks
  • @the-notable
  • @mirkoRainer
  • @Iaiao
  • @hymm
  • @jacobgardner
  • @Protowalker
  • @godsmith99x
  • @Weibye
  • @lberrymage
  • @anchpop
  • @willolisp
  • @trolleyman
  • @msklywenn
  • @deontologician
  • @johanhelsing
  • @memoryruins
  • @ahmedcharles
  • @vabka
  • @bytebuddha
  • @louisgjohnson
  • @r00ster91
  • @parasyte
  • @illuninocte
  • @jihiggins
  • @Dimev
  • @szunami
  • @tiagolam
  • @payload
  • @mrk-its
  • @Ixentus
  • @dintho
  • @CptPotato
  • @bjorn3
  • @CAD97
  • @lwansbrough
  • @Ratysz
  • @vgel
  • @dixonwille
  • @KirmesBude
  • @Tobenaii
  • @pbalcer
  • @msvbg
  • @Philipp-M
  • @Waridley
  • @StarArawn
  • @ickk
  • @IceSentry
  • @Lythenas
  • @Shatur
  • @Grindv1k
  • @aevyrie
  • @wilk10
  • @Davier
  • @timClicks
  • @DJMcNab
  • @r4gus
  • @rparrett
  • @mfdorst
  • @Veykril
  • @thebluefish
  • @forbjok
  • @bytemuck
  • @dbearden
  • @OptimisticPeach
  • @Weibye-Breach
  • @MrGVSV
  • @RichoDemus
  • @R3DP1XL
  • @jak6jak
  • @blaind
  • @YohDeadfall
  • @cart
  • @MinerSebas
  • @CrazyRoka
  • @NiklasEi
  • @superdump
  • @lassade
  • @yetanothercheer
  • @64kramsystem
  • @mockersf
  • @billyb2
  • @molikto
  • @mtsr
  • @Abhuu
  • @kumorig
  • @yilinwei
  • @Nilirad
  • @SarthakSingh31
  • @Frizi
  • @dataphract
  • @Sheepyhead
  • @simensgreen
  • @NathanSWard
  • @remilauzier
  • @fluffysquirrels

完整变更日志 #

新增 #