D3D9 Samples(14)--StateManager

来源:互联网 发布:光线投射算法原理 编辑:程序博客网 时间:2024/06/06 03:23

 

 

 

D3D9 Samples(14)--StateManager

 

 

 

       打开StateManager项目。编译运行:

 

 

        这个例子渲染了一个较复杂的场景,有凉亭、树木、石头、地形和天空盒。每个网格又包含多个材质,每个材质的effect都不同。所以在渲染时,渲染队列(render sequence)需要进行多次状态(state)变化。这个列子信息量很大,写了很多封装类,主要展示两种优化性能的方法:第一种,通过ID3DXEffectStateManager来统计状态变化次数,过滤掉冗余的状态变化。第二种,对渲染序列进行重新排序,大大提高渲染效率。

 

 

1. 过滤冗余状态变化(redundant state changes)

 

1.1 D3DCREATE_PUREDEVICE

 

如果在IDirect3D9::CreateDevice中使用了这个标记,表明创建了一个pure device。一个Pure device在状态变化(state changes)时不保存当前的状态,这样可以提高性能。这个标记一般在程序发行时启用,以获得最佳性能。但是它有两个缺点:一是,它不支持IDirect3DDevice9中所有Get*方法。二是,它不进行冗余状态变化(redundant state changes)过滤,所以应用程序必须自己在渲染中尽可能的减少状态变化。而非pure device会自动进行过滤,但是最终发布的D3D9程序应该是使用pure device的,所以这个例子主要展示在使用pure device时如何减少冗余状态变化,达到非pure device的效果。

 

 

1.2 ID3DXEffectStateManager

 

如果使用effect来渲染,则这个接口提供了给开发者用来设置状态或统计Set*方法次数的途径。首先用CStateManagerInterface在ID3DXEffectStateManager基础上增加两个方法:

virtualvoid   DirtyCachedValues() = 0;

使缓冲中的状态变化值无效,从而删减冗余的状态变化。

 

virtual LPCWSTR EndFrameStats() = 0;

统计渲染一帧(frame)进行了多少次状态变化。

 

CBaseStateManager

用于非pure device。这个设备会自动过滤掉冗余的状态变化。注意每个Set*方法最终还是通过调用IDirect3DDevice9的Set*方法去实现,但是增加了个m_nTotalStateChanges++用来计数。

 

CPureDeviceStateManager

用于pure device。这个设备不会过滤冗余的状态变化。所以这里在SetRenderState、SetSamplerState、SetTextureStageState三个方法中加了过滤逻辑。

 

 

 

2. 加载数据

 

进入OnCreateDevice:

BuildSceneFromX

首先通过LoadSceneFromX读取X文件。

然后遍历数据,为每个网格创建实例CInstance。从而得到一个可渲染的实例列表。

 

QueueAndSortRenderables

遍历上面的实例列表。根据材质来重新排序上面的渲染列表。并且得到一个通道(pass)列表。

 

SetStateManager

为effect选择一个state manager。

 

 

 

3. 对渲染序列(Render Sequence)进行重新排序

 

SortRenderables

根据材质(Material)对要渲染的通道进行排序。

 

 

 

 

参考资料

 

http://msdn.microsoft.com/en-us/library/windows/desktop/ee416788(v=vs.85).aspx

 

http://msdn.microsoft.com/en-us/library/windows/hardware/ff569212(v=vs.85).aspx