1.平台独立
虽然我基本思想是借助D3D来实现我的渲染器,但是可能是潮流所致,让我在设计要用到的概念时考虑了将来如果我想玩一把OPGL会怎么样.通过纹理类的设计,我想理请我的思路,也请高手指教.
在3D渲染时所谓纹理,需要考虑四个方面( 以我的认识来看 ):
(1)纹理的存储位置与文件名
(2)纹理的过滤方式
(3)纹理的寻址方式
(4)纹理的对应采样器Unit
提取了基本成员后,就开始考虑类的设计问题,由于我希望平台独立,因此在这个类中,我不会存放资源(这里的资源指的是LPDIRECT3DTEXTURE这样对应于D3D平台的纹理存放单元),而是设计一种资源管理机制,在DX渲染器用到某纹理时,针对纹理实例的成员内容实时的申请资源,所以,在纹理类的设计时,只需要考虑抽象的概念,具体到DX时再进行映射就可以了.
2.映射到DX的例子
假设在纹理类中,我定义了一个枚举类型来表示寻址方式如下:
enum WrapType
{
CLAMP,
REPEAT,
MIRRORED_REPEAT,
CLAMP_BORDER,
CLAMP_EDGE,
MAX_WRAP_TYPES
};
又假设当前的寻址类型为CLAMP,那么在DX中使用SetTexture前,针对纹理寻址方式的设置可以如下编写:
(1)在DX渲染器中定义一个对应的数组
DWORD JLY_1DxRenderer::ms_adwTexWrapMode[JLY_1Texture::MAX_WRAP_TYPES] =
{
D3DTADDRESS_CLAMP, // Texture::CLAMP
D3DTADDRESS_WRAP, // Texture::REPEAT
D3DTADDRESS_MIRROR, // Texture::MIRRORED_REPEAT
D3DTADDRESS_BORDER, // Texture::CLAMP_BORDER
D3DTADDRESS_CLAMP, // Texture::CLAMP_EDGE
};
(2)根据纹理的相关成员进行设置
ms_hResult = m_pqDevice->SetSamplerState(iTextureUnit,
D3DSAMP_ADDRESSU,ms_adwTexWrapMode[pkTexObj->GetWrapType(0)]);
assert(SUCCEEDED(ms_hResult));
ms_hResult = m_pqDevice->SetSamplerState(iTextureUnit,
D3DSAMP_ADDRESSV,ms_adwTexWrapMode[pkTexObj->GetWrapType(0)]);
assert(SUCCEEDED(ms_hResult));
从上面可以看见,以后如果我想把这个纹理类应用到OPGL的平台下,只需要在OPGL渲染器中写出对应的映射就可以了.当然除了纹理,像顶点缓冲,索引缓冲,Shader等资源,都可以象上面一样写成平台独立的方式,你所要做的就是两步,一,在使用这个概念的时候完成资源申请,二,在渲染器中编写映射.
3.纹理的Sampler Unit
好象在这里说这个有点突兀,但是我只是想说明为什么我在纹理类中要放一个这样的成员,我在刚开始接触DX时都没有注意到采样器对于纹理来说的重要性,但是随着shader的学习我发现,很多纹理的特殊效果要是离开Sampler Unit是不可想象的,比如两个纹理的混合,如果没有正确的匹配纹理与采样器,你会很痛苦( 我就痛苦过... )
研究过Shader的人都知道,在shader中声明sampler的顺序决定了Sampler Unit,比如:
Sampler2D s[ 2 ];
那么s[ 0 ]的unit = 0, 而S[ 1 ]的unit = 1;
在程序中,如果你希望纹理设置到对应的Sampler中,在调用SetTexture时,就必须填入对应的unit,这就是为什么我要在纹理类中加一个这样的属性的原因.因为你的纹理需要知道自己到底应该跟谁携手让世界变的更美丽^^
Enjoy!!