Opengl 如何管理纹理

Opengl 如何管理纹理,opengl,3d,textures,Opengl,3d,Textures,我正在基于OpenGL编写一个简单的3D引擎(我知道有很多,但出于某些原因,我想自己学习如何做到这一点)。我对我目前的场景图和类似的东西很满意,但对纹理处理我很不满意。所以我想知道如何正确地做到这一点 当我看互联网上的示例代码时,他们从来没有提到如何管理纹理。他们只是在应用程序启动时加载一些纹理,显示演示内容,然后程序退出。但是如果我经常改变场景中的东西呢?如果我想显示一个具有10个纹理的场景,然后在场景中删除一个节点,这样就不再需要2个纹理,然后添加一个具有4个新纹理的新节点,该怎么办。因此,

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

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


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

如果你在C++中实现它,最简单的方法就是拥有一个可以自己加载和卸载的纹理类。每当加载对象时,它也会加载所需的纹理。当该对象离开时,它会破坏它加载的纹理,从而卸载它们

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

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


你可能会对引用计数和全球经理感到棘手,但是,你还需要想出一个整理内存碎片的方案等等,这是一个有趣的学术练习,但随着项目接近完成,最终会造成太多的麻烦。

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


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

具有引用跟踪和内存碎片整理功能的全局管理器是我唯一专业使用的工具,因此我肯定会说这是一个可行的解决方案。当然,我只是觉得成本非常高,只有当很多人在游戏中投入大量资产时,价值才会显现出来。