3D 文本

前言

项目中不仅会要在 HUD 中使用文本,有时也会需要把文本作为 3D 场景的一部分。Godot 为此提供了两种方法。Label3D 节点以及 MeshInstance3D 节点的 TextMesh 资源

此外,Godot 还可以使根据 3D 顶点在相机上的位置来定位控制节点成为可能。在 Label3D 和 TextMesh 不够灵活的情况下,这可以用作 “真实的” 3D 文本的替代方案。

参见

你可以使用 3D 标签和文本演示项目 查看3D文本的实际效果。

这个页面不会涉及如何在 3D 环境中显示 GUI 场景。有关如何实现这个功能的信息,请参考GUI in 3D 演示项目。

Label3D

../../_images/label_3d.png

Label3D 的行为类似于 Label 节点,只不过是换到了 3D 空间中。与 Label 节点不同,此 Label3D 节点继承 GUI 主题的属性。不过,外观还是可定制的,使用的也是与 Control 节点相同的字体子资源(包括对 MSDF 字体渲染的支持)。

优势

  • Label3D 的生成速度比 TextMesh 快。虽然两者都使用缓存机制,只渲染一次新字形,但 Label3D 的(重新)生成速度仍然更快,尤其是对于长文本。这可以避免在低端 CPU 或移动设备上玩游戏时出现卡顿。

  • Label3D 可以使用位图字体和动态字体(带或不带 MSDF 或 mipmap)。这使得它在这方面比 TextMesh 更灵活,尤其是在渲染具有自交轮廓的字体时。

参见

有关配置字体导入的指南,请参阅 使用字体

限制

默认情况下,Label3D 与 3D 环境的交互有限。 着色 标志启用时能够接受光照、被光源着色。但是,即使在 Label3D 的 GeometryInstance3D 属性中将 阴影投射 设置为 开启 ,它也不会投射阴影。这是因为该节点内部生成具有透明纹理的四边形网格(每个四边形一个字形),并且具有与 Sprite3D 相同的限制。当多个 Label3D 重叠,尤其是当它们具有轮廓时,透明度排序问题也会变得明显。

这可以将 Label3D 的透明度模式设置为 Alpha Cut 来缓解 ,但代价是文字渲染不够流畅。Opaque Pre-Pass 透明度模式可以保持文本的流畅性,同时允许 Label3D 投射阴影,但仍会存在一些透明度排序问题。

有关详细信息,请参阅 3D 渲染限制页面中的 Transparency sorting 部分。

TextMesh

../../_images/text_mesh.png

TextMesh(文本网格)资源和 Label3D 类似,都能够在 3D 场景中显示文本,使用的是相同的字体子资源。但 TextMesh 生成的不是透明四边形,而是代表字形轮廓的 3D 网格,具有和网格一样的属性。因此,TextMesh 默认是开启着色的,会自动在环境中投射阴影。TextMesh 也可以设置材质(包括自定义着色器)。

这是为网格应用纹理的示例。你可以使用下面的纹理作为生成网格 UV 贴图的参考:

../../_images/text_mesh_texture.png ../../_images/text_mesh_textured.png

优势

相对于 Label3D 而言,TextMesh 有以下优点:

  • TextMesh 可以使用纹理来修改文本各个面的颜色。

  • TextMesh 几何体具有深度,字形看上去是 3D 的。

  • TextMesh 可以使用自定义的着色器,而 Label3D 无法使用。

限制

TextMesh 的局限性有:

  • 没有内置的轮廓支持,而 Label3D 支持。但是可以使用自定义着色器模拟。

  • 仅支持动态字体(.ttf.otf.woff.woff2)。不支持 .fnt.font 格式的位图字体。

  • 无法正确渲染轮廓自相交的字体。如果使用从 Google Fonts 等处下载到的字体时出现渲染问题,请尝试改为从作者的官方网站下载。

投影 Label 节点(或者其他 Control 节点)

还有最后一种设置起来更麻烦的解决方案,但是灵活性更高:将 2D 节点投影到 3D 空间中。做法是在脚本的 _process() 函数中使用 Camera3D 节点的 unproject_position 的返回值。使用这个返回值来设置 Control 节点的 position 属性。

示例见 3D 路径点演示。

优势

  • Label、RichTextLabel 等任何 Control 节点,甚至 Button 这样的节点都可以用这种方法。这样就能够实现强大的格式和 GUI 交互。

  • 基于脚本的做法能够在定位方面做到最大的自由度。例如,这样就能够在超出屏幕范围后将 Control 吸附到屏幕的边缘(用于在游戏中实现 3D 标记)。

  • Control 主题仍然有效。这样实现自定义项目全局的设置就更方便。

限制

  • 投影的 Control 无法以任何形式被 3D 几何体遮挡。目标位置被遮挡时,你可以借助 RayCast 将该控件完全隐藏,但是无法实现位于墙壁后面时只隐藏部分区域的效果。

  • 可以根据距离调整 Control 的 scale 属性,从而调整文本的大小,但是需要手动缩放。Label3D 和 TextMesh 会自动处理,但是灵活性不足(无法设置最小/最大的文本像素大小)。

  • 必须在脚本中考虑到分辨率和纵横比的变化,这可能具有挑战性。

我应当使用 Label3D,TextMesh 还是投影的 Control?

在大多数情况下,建议使用 Label3D,因为它更易于设置,并能提供更高的渲染质量(尤其是在禁用 3D 抗锯齿的情况下)。

对于进阶用例,TextMesh 更为灵活,因为它允许使用自定义着色器对文字进行设计。自定义着色器可以修改最终几何图形,例如沿表面弯曲文字。由于文字是实际的三维几何体,因此文字可以选择具有深度,也可以对全局照明做出贡献。

如果你需要 BBCode 或 Control 主题支持等功能,则使用投影 RichTextLabel 节点是唯一的方法。

Previous Next


© 版权所有 2014-present Juan Linietsky, Ariel Manzur and the Godot community (CC BY 3.0). Revision b1c660f7.

Built with Sphinx using a theme provided by Read the Docs.