資源異步加載恐怕是3D引擎中應(yīng)用最為廣泛的多線程技術(shù)了,特別是在無縫地圖的網(wǎng)絡(luò)游戲中,尤為重要,公司3D引擎的資源加載部分采用了硬盤->內(nèi)存->顯存兩級加載的模式,超時卸載也分兩級,這樣雖然實際效果不錯,但代碼非常繁瑣,在FlagshipEngine中,我設(shè)法將其進行了一定程度的簡化。
首先我們需要定義一個Resource基類,它大致上是這樣的:
class _DLL_Export Resource : public Base

{
public:
Resource();
virtual ~Resource();

// 是否過期
bool IsOutOfDate();


public:
// 是否就緒
virtual bool IsReady();

// 讀取資源
virtual bool Load();

// 釋放資源
virtual bool Release();

// 緩存資源
virtual bool Cache();

// 釋放緩存
virtual void UnCache();

protected:
// 加載標(biāo)記
bool m_bLoad;

// 完成標(biāo)記
bool m_bReady;


private:

};
在實際游戲中,加載資源的范圍大于視野,當(dāng)攝像機移動到單元格邊緣(必須有一定的緩沖區(qū)),就應(yīng)將新的單元格中的對象加入到資源加載隊列中,喚醒資源加載線程調(diào)用Load接口進行加載,完成后將該資源的加載標(biāo)記設(shè)為true。而通過可視剪裁所得到的最終可視實體,則需要調(diào)用Cache接口構(gòu)建圖像API所需對象,當(dāng)Load和Cache都完成后IsReady才會返回true,這時該資源才能開始被渲染。
卸載方面,在加載新的單元同時,卸載身后舊的單元,對單元內(nèi)所有資源調(diào)用Release,Load/Release帶有引用計數(shù),仍被引用的資源不會被卸載。當(dāng)某一資源長時間沒有被看見,則超時,調(diào)用UnCache釋放VertexBuffer等資源。
為了實現(xiàn)超時卸載功能,我們需要一個ResourceManager類,每幀檢查幾個已Cache的資源,看起是否超時,另外也需對已加載的資源進行分類管理,注冊其資源別名(可以為其文件名),提供查找資源的接口。
另外為了方便使用,我們需要一個模板句柄類ResHandle<T>,設(shè)置該資源的別名,其內(nèi)部調(diào)用ResourceManange的查找方法,看此資源是否已存在,如不存在則new一個新的,GetImpliment則返回該資源對象,之后可以將該資源添加到實體中,而無需關(guān)心其是否已被加載,代碼如下:
template <class T>
class _DLL_Export ResHandle

{
public:

ResHandle()
{ m_pResource = NULL; }

virtual ~ResHandle()
{}

// 設(shè)置資源路徑
void SetPath( wstring szPath )

{
Resource * pResource = ResourceManager::GetSingleton()->GetResource( Key( szPath ) );
if ( pResource != NULL )

{
m_pResource = (T *) pResource;
}
else

{
m_pResource = new T;
m_pResource->SetPath( szPath );
ResourceManager::GetSingleton()->AddResource( m_pResource );
}
}

// 模板實體類指針

T * GetImpliment()
{ return (T *) m_pResource; }


T * operator-> ()
{ return (T *) m_pResource; }

protected:
// 模板實體類指針
Resource * m_pResource;

private:
};
首先我們需要定義一個Resource基類,它大致上是這樣的:









































卸載方面,在加載新的單元同時,卸載身后舊的單元,對單元內(nèi)所有資源調(diào)用Release,Load/Release帶有引用計數(shù),仍被引用的資源不會被卸載。當(dāng)某一資源長時間沒有被看見,則超時,調(diào)用UnCache釋放VertexBuffer等資源。
為了實現(xiàn)超時卸載功能,我們需要一個ResourceManager類,每幀檢查幾個已Cache的資源,看起是否超時,另外也需對已加載的資源進行分類管理,注冊其資源別名(可以為其文件名),提供查找資源的接口。
另外為了方便使用,我們需要一個模板句柄類ResHandle<T>,設(shè)置該資源的別名,其內(nèi)部調(diào)用ResourceManange的查找方法,看此資源是否已存在,如不存在則new一個新的,GetImpliment則返回該資源對象,之后可以將該資源添加到實體中,而無需關(guān)心其是否已被加載,代碼如下:

















































