2009年2月2日星期一

Nebula3资源系统

关于资源系统的更多信息。因为还在开发中,所以一些细节像类名可能会改变。一般讲,Nebula3资源系统足够的开放,并且相对于N2给开发人员对于资源的创建和管理更多的控制。

Nebula3资源有一下特性:

1.包装其它Nebula系统需要的各种数据。
2.能通过ResourceId共享。
3.在任何时候可以被加载和卸载。
4.可以被同步或者异步加载。

典型的图形资源如网格和纹理,然而资源系统不仅限于图形资源。

资源系统有两个操作层面(这可能被分为两个不同的命名空间,但目前都是放在Resources命名空间下):

底层提供了实际的资源对象,处理资源的共享,加载和保存。底层的资源类:

1.ResourceId
2.Resource
3.ResourceLoader
4.ResourceSaver
5.SharedResourceServer

资源系统的高层提供了资源管理,这意味着根据资源使用者的反馈动态地加载或者卸载资源。资源系统的高层类:

1.ResourceProxy(也可能选择类名:ManagedResource)
2.ResourceProxyServer(也可能选择类名:ResourceManager)
3.ResourceMapper

资源系统的这些类是如何一起工作的:

ResourceId是资源唯一标识符。资源标识符被用来共享,和定位磁盘资源数据的位置。资源标识符是一个具有原子性的字符串。使用一个唯一的32位标识来表式常量字符串,可以提高字符串拷贝和比较的效率,并且降低内存的使用,因为相同的字符串只会存储一次。为定位磁盘上的资源数据,资源标识符一般解析成一个有效的URI(一个资源标识符看起来像“texture:materials/granite.dds”这样,在运行的时被解析成像“file:///C:/Programme/[AppName]/export/textures/materials/granite.dds”这样)。

一个Resource对象才是真正的资源数据容器。特殊的资源类型像纹理和网格是Resource的子类并提供专门的类接口。Resource的子类经常是平台相关的(例如:D3D9Texture),但根据条件typedef一个平台无关的接口(例如:Texture)。不像在Nebula2中,资源对象不知道如何设置,加载和保存自己。替代的是,一套合适的ResourceLoader和ResourceSaver对象被增加到Resource对象中。Nebula应用程序很少需要输出数据,ResourceSaver更多的是为了完整性而存在。另一方面,ResourceLoaders是很重要的,因为它是设置Resource对象的唯一途径。ResourceLoaders完全控制了资源设置的过程。它们可能平台相关,也可能依赖一个与平台相关的Resource类。这相比于Nebula2给程序员更多控制资源设置过程。例如资源加载
类:StreamTextureLoader,StreamMeshLoader(从流中设置纹理和网格),MemoryVertexBufferLoader和MemoryIndexBufferLoader(从内存中的数据设置顶点缓存和索引缓存)。

Resource类为资源的同步加载和异步加载提供一个相同的接口。同步加载像下面这样:

1. res-> SetResourceId("tex:system/white.dds");
2. res-> SetLoader(StreamTextureLoader::Create());
3. res-> SetAsyncEnabled(false)
4. res-> Load()
5. if (res-> IsValid()) ... then resource loading was successful, otherwise the method
LoadFailed() will return true.

异步加载和上面非常相似:

1. res->SetResourceId("tex:system/white.dds");
2. res->SetLoader(StreamTextureLoader::Create());
3. res->SetAsyncEnabled(true);
4. res->Load();
5. the resource will now go into pending state...
6. as long as IsPending() returns true, repeatedly call Load()... of course a real application
would do something useful in the meantime
7. at some point in the future, after Load() is called, the state of the resource will either be
Valid (resource is ready for use), Failed (loading the resource has failed) or Cancelled (the
pending resource load has been cancelled)

一个应用程序或者甚至Nebula3的渲染代码通常不需要处理这一些,资源管理层将处理这些事情并把资源异步加载的细节隐藏在资源代理后面。

单例SharedResourceServer通过ResourceId共享资源。通过SharedResourceServer创建资源必须确定资源被正确地加载到内存中,不管它的客户端计数。如果一个资源的客户端计数减为0的时候,该资源将自动卸载掉。如果通过Nebula3标准的对象创建机制创建资源对象那么将无法进行资源共享。

ResourceProxy(或ManagedResource)是包装实际资源对象的代理对象。这个想法是基于资源使用情况的反馈,被包含的资源对象在资源管理器的控制下可能会发生改变。例如,一个TextureProxy可对象以在请求后台加载纹理的时候提供一个占位的纹理,假如所有的对象都在屏幕很小的地方使用这个资源那么可以提供一个低分比率的纹理,该纹理在X帧后没有被渲染就可以卸载掉。

单例ResourceProxyServer(或ResourceManager)是资源管理系统的前端。它是ResourceProxy类的工厂并且关联了和资源类型相关的ResourceMappers。

ResourceMapper是一个有趣的类。一个ResourceMapper和一种资源类型相关联(例如.纹理或网格)并通过应用程序添加到ResourceProxyServer中。一个ResourceMapper的职责是根据渲染代码使用资源的反馈加载或卸载资源。ResourcMapper的子类可以实现不同的资源管理策略,也可以通过派生特定的ResourceMapper和ResourceLoader的子类来创建一个完全定制,平台和应用相关的资源管理方案。显而易见,Nebula3提供了一些开箱即用的ResourMapper类。

资源使用情况的反馈是通过渲染代码写入ResourceProxy对象的并包含了其它一些信息如:资源在不久的将来还会需要吗?资源是否可见?并估计物体占用的屏幕空间大小。然而不同的反馈依赖ResourceProxy子类,在ResourceProxy类中没有相同的反馈方法。

根据资源使用的反馈,一个ResourceMapper需要实现如下操作:

1. Load: 在特定的层次细节(level-of-detail)上异步加载资源,在加载的时候为资源提供一个占位资符。
2. Unload: 完全卸载资源,释放有用的内存。
3. Upgrade:提高一个已经加载的资源层次细节。
4. Degrade:降低一个已经加载的资源层次细节。

原文: The Nebula3 Resource Subsystem

[声明]:限于译者水平,文中难免错漏之处,欢迎各位网友批评指正;

没有评论:

发表评论