DX9和DX11的API相差非常大,如果一个引擎要支持两种渲染器,在设计上还是要花点功夫。也可以参考OGRE和klayge的,不过klayge已经去掉了DX9的渲染器了。
在我自己的引擎中,我之前封装的渲染状态就一个类叫Shader,这里面封装了一大堆渲染状态,就是和DX9比较匹配,但如果引擎要过渡到支持DX10以上的,就比较麻烦了。
根据DX11的API,可以把渲染状态分类封装起来,大概如下:
blend混合的:
class BlendStateObject
rasterizer相关:
class RasterizerStateObject
深度相关:
class DepthStencilStateObject
等等。
这些其实和DX11的API是匹配的,在DX9中也可以把一大堆渲染状态按这样的方式分类,但是这样问题来了:DX9有固定管线的一堆状态,该往哪放呢?ogre是再细分一下,我在AIREngine中就直接把一些固定管线状态封装成一个类叫FixedPineStateObject,这个类里面有AlphaTest,Fog等固定管线的状态。
这些状态都有这样一个接口:
class XXXStateObject
{
public:
virtual void Apply() = 0;
}
这个接口是用于提交渲染状态的,这样封装还有一个非常大的好处,可以把渲染器的基类的接口再简化一些,以下代码就可以看到这样的方便之处:
class DX9XXXStateObject : public XXXStateObject
{
public:
virtual void Apply()
{
DX9Renderer* pRenderer = (DX9Renderer*)GetRenderer();
pRenderer->SetRenderState(xxx); //这里的SetRenderState只是DX9提供的,如果按以前的做法,渲染器基类也要封装这样一个SetRenderState,非常不方便。
}
}
正如这段代码,基类的渲染器可以减少非常多的和DX9和DX11 API相关的接口了,好处非常明显。