【问题标题】:How to manage textures如何管理纹理
【发布时间】:2011-04-13 04:59:32
【问题描述】:

我正在编写一个基于 OpenGL 的简单 3D 引擎(我知道那里有很多,但出于某些原因,我想自己学习如何做)。我对我目前的场景图方法和类似的东西非常满意,但我对纹理处理非常不满意。所以我想知道如何正确地做到这一点。

当我查看互联网上的示例代码时,他们从不谈论如何管理纹理。他们只是在应用程序启动时加载一些纹理,显示他们的演示内容,然后程序退出。但是如果我经常改变场景中的东西怎么办?如果我想显示一个具有 10 个纹理的场景,然后我删除场景中的一个节点以便不再需要 2 个纹理,然后我添加一个具有 4 个新纹理的新节点,该怎么办?所以必须从视频 RAM 中删除 2 个旧纹理,我必须添加 4 个新纹理。然后我完全替换了整个场景,因此必须再次删除所有未使用的纹理,并且必须加载新的纹理,而必须重新使用之前使用过的并且也在新场景中使用的纹理。这听起来很复杂。

如何在专业 3D 引擎中管理纹理?它是一个全局单例纹理管理器,它使用引用计数器跟踪纹理使用情况并不时清理视频内存吗?还是有更天才的方法来做到这一点?

【问题讨论】:

    标签: opengl 3d textures


    【解决方案1】:

    我认为您需要在这里意识到的是,您要解决的问题并不是纹理所独有的,而是所有游戏资源所独有的。我认为最好的解决方案是结合引用计数的依赖跟踪的自动化方法。对于您想要在游戏中使用的每个“事物”,您应该有某种根文件来引用该“事物”使用的所有其他资产(声音、纹理、模型、粒子效果)。您应该有某种工具或构建脚本来打包每个项目的所有资产。在创建任何“事物”之前,您需要加载适当的包。您加载的每件事都添加引用包,然后包添加引用所有加载的资源。一旦 ref 计数变为 0,您就知道删除资源或整个 pacakges 是安全的。

    这种方法的另一个好处是您可以给自己分配内存预算,并在构建时而不是运行时检查它们,因为您知道每个包有多大。此外,包可以共享资源,因此如果另一个包已经添加了它,您可以确保不要多次加载它们。

    【讨论】:

      【解决方案2】:

      如果您在 C++ 中实现它,“最简单”的方法就是拥有一个可以自行加载和卸载的 Texture 类。每当一个对象加载时,它也会加载它需要的纹理。当该对象消失时,它会破坏它加载的纹理,从而卸载它们。

      C 中的解决方案是类似的;您有一个包含足够数据的结构,以便在需要将其从 vram 中取出并释放其资源时“卸载”该纹理。

      这基本上是我们在“专业游戏”中所做的,尽管在我目前正在制作的系列中,每个世界区域都会引入它需要的所有纹理,因此该区域中具有相同纹理的每个对象共享相同的纹理数据。相邻区域可能有具有相同源纹理的对象,但在这种情况下,我们只让内存中有两个副本,因为管理更容易。

      您可能会在引用计数和全局管理器方面变得棘手,但是您还需要想出一个对内存进行碎片整理等等的方案,这是一个有趣的学术练习,但最终会导致太多项目接近完成时遇到麻烦。

      【讨论】:

      • 具有引用跟踪和内存碎片整理功能的全局管理器是我唯一专业使用过的东西,所以我肯定会说它是一个可行的解决方案。
      • 当然,我只是觉得成本很高,只有当你有很多人在游戏中投入大量资产时,价值才会开始显现。
      猜你喜欢
      • 2023-04-01
      • 2018-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      相关资源
      最近更新 更多