无论是在现实生活中还是在游戏虚拟世界中,将任何一个物体进行投影,然后进解析,都会发现它是由若干个多边形所构成,再将多边形进行分解,可以划分为若干个四边形和三角形,再将四边形进行分解,可以发现,四边形又可以划分为2个或以上的三角形构成。
因此就是采用这种方法,将图像数据映射到三角形单元中去。
纹理映射技术,是一种将图形绘制(映射)到表面的技术,可以显著地增加所绘制场景的细节和真实感。
如:
struct Vertex
{
float _x,_y,_z;
float _nx,_ny,_nz;
float _u,_v;
static const DWORD FVF;
};
const DWORD Vertex::FVF=D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1;
值得注意的是:当为一个3D三角形指定相应的纹理三角形时,并不是马上就会进行纹理映射,是直到光栅化的时候,纹理映射才会进行。
创建纹理:
一般纹理的数据都是从磁盘中的图像文件读入,然后再加载到IDirect3DTexture9对象中;同样该图像文件可以在场景中的多个表面上共享使用。
Direct3D支持的图像文件格式有:
.jpg; .bmp; .tga; .png; .dds; .ppm; .dib; .hdr; .pfm;
从文件中加载纹理并将其加载到内存中,使用D3DXCreateTextureFromFile()函数
HRESULT D3DXCreateTextureFromFile(
LPDIRECT3DDEVICE9 pDevice, //设备对象
LPCTSTR pSrcFile, //所需加载的图像文件名
LPDIRECT3DTEXTURE9 *ppTexture //定义一个指针用来接收所创建的纹理
);
如果想让文件所加载的图像发挥更多的控制作用,可以使用D3DXCreateTextureFromFileEx()函数
HRESULT D3DXCreateTextureFromFileEx(
LPDIRECT3DDEVICE9 pDevice, //设备对象
LPCTSTR pSrcFile, //所需加载的图像文件名
UINT Width, //图像宽度
UINT Height, //图像高度
UINT MipLevels, //图片的图层,与图像质量有关
DWORD Usage, //设定纹理的使用方法
D3DFORMAT Format, //每个颜色使用的位数(8,16,24,36)
D3DPOOL Pool, //纹理对象驻留的内存类别
DWORD Filter, //处理图像质量的方法
DWORD MipFilter, //像素过滤方式
D3DCOLOR ColorKey, //设置透明色
D3DXIMAGE_INFO *pSrcInfo, //记录载入图片信息
PALETTEENTRY *pPalette, //记录调色板信息
LPDIRECT3DTEXTURE9 *ppTexture //用来接收所创建的纹理
);
现在已经知道加载纹理的函数了,那怎么使用?
比如现在要加载一个名为“hell.bmp”的图像文件创建纹理:
1、创建设备对象和用来接收所创建纹理的指针
LPDIRECT3DDEVICE9 Device;
IDiretct3DTexture9 *_hell;
D3DXCreateTextureFromFile(Device,
"hell.bmp", //如果不是放在当前项目下,就加上路径名
&_hell);
2、设置当前纹理,使用SetTexture()函数
//SetTexture()的函数原型
HRESULT SetTexture(
DWORD Sampler, //纹理要施加的采样器阶段,该值在[0,7]
IDirect3DBaseTexture9 *pTexture //Direct3D9纹理对象
);
Device->SetTexture(0,_hell);
LPDIRECT3DDEVICE9 Device;
Device->SetSmaplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT);//放大
Device->SetSmaplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT);//缩小
2、线性纹理过滤(linear filtering):该方式可以产生较好的效果,而且速度也是蛮快的,内存开销比较适宜得当。
Device->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);//放大
Device->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);//缩小
3、各向异性纹理过滤(anisotropic filtering):该方式可以产生最好的过滤效果,但处理速度却是最慢的,内存的开销也是最大的。再进行使用各向异性纹理过滤时,必须对D3DSAMP_MAXANISOTROPIC水平值进行设定,该值决定了各向异性过滤的质量水平,值越大,图像效果就越好。不过在使用前先使用GetDeviceCaps()函数进行检测下,看硬件能支持的数值是多少。
Device->SetSmaplerState(0,D3DSAMP_MAXANISOTROPIC,3);//假设值为3
Device->SetSmaplerState(0,D3DSAMP_MAGFILETER,D3DTEXF_ANISOTROPIC);//放大
Device->SetSmaplerState(0,D3DSAMP_MINFILETER,D3DTEXF_ANISOTROPIC);//缩小
4、多级渐进纹理(mipmap):由某一纹理的原式分辨率创建一系列逐渐减小(将像素分别缩小一半)的纹理图像,并且对每种分辨率下的纹理所采用的过滤方式进行定制,以便保留那些比较重要的细节。
Device->SetSamplerState(0,D3DSAMP_MIPFILTER,Filter);
Fileter可以取以下值:
D3DTEXF_NONE: 禁用多级渐进纹理过滤。
D3DTEXF_POINT: 采用最近点采样(nearest point sampling)进行过滤。
D3DTEXF_LINEAR: 采用线性纹理(linear filtering)进行过滤。
寻址模式
上面说过纹理坐标必须限制在[0,1]范围内,如果超出那怎么办,Direct3D提供了四种用来处理纹理坐标值超出[0,1]区间的纹理映射模式。
重复寻址模式(wrap address mode):
Device->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
Device->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
Device->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_BORDER);
Device->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_BORDER);
Device->SetSmaplerState(0,D3DSAMP_BORDERCOLOR,0x000000ff);
Device->SetSmaplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
Device->SetSmaplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
Device->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_MIRROR);
Device->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_MIRROR);
最后上传源代码(有点小问题,不过无伤大雅)
源码链接