如何管理纹理

时间:2010-09-16 12:41:36

标签: opengl 3d textures

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

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

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

2 个答案:

答案 0 :(得分:4)

我认为你需要意识到的是,你想要解决的问题并不是纹理所独有,而是你所有的游戏资源。我认为最好的解决方案是依赖跟踪的自动化方法与ref计数相结合。对于你想要在游戏中使用的每个“东西”,你应该有一些根文件引用那个“东西”使用的所有其他资产(声音,纹理,模型,粒子效果)。您应该使用某种工具或构建脚本来打包每个项目的所有资产。在创建任何“东西”之前,您需要加载相应的包。您加载的每个东西都会枚举包,反过来包中会添加所有加载的资源。一旦参考计数变为0,您就知道可以安全地移除资源或整个资源。

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

答案 1 :(得分:3)

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

C中的解决方案类似;你有一个结构包含足够的数据来“卸载”该纹理,当它从vram中取出并释放其资源时。

这基本上就是我们在“专业游戏”上做的事情,虽然在我正在研究的每个世界区域的系列中都会拉入所需的所有纹理,因此该区域中具有相同纹理份额的每个对象相同的纹理数据。相邻区域可能具有相同源纹理的对象,但在这种情况下,我们只是让内存中有两个副本,因为管理更容易。

你可能会因为引用计数和全局经理而变得棘手,但是你还需要提出一个对内存进行碎片整理的方案,等等,这是一个有趣的学术练习,但最终会导致太多项目接近完成时出现问题。