【阅读笔记之八】《DIRECTX.9.0.3D游戏开发编程基础》:Direct3D中的纹理与映射
Direct3D中的纹理与映射
在Direct3D中,借助纹理映射(texture mapping)技术可将图像数据映射到三角形单元,从而显著地所绘制图景的细节和真实感。纹理用接口IDirect3DTexture9来表示。纹理类似于表面的一个像素矩阵,与表面不同的是它可被映射到三角形单元。
这一章主要学习:
1)如何将纹理的某一部分映射到三角形单元中;
2)掌握如何创建纹理;
3)掌握为创建一幅较光滑的图像,纹理应如何过滤;
1. 纹理坐标
Direct3D所用的纹理坐标系有沿着水平方向的u轴和沿垂直方向的v轴(竖直向下)构成。用坐标对(u,v)标识的纹理元素称为纹理元(texel)。另外,Direct3D为了处理不同尺度的纹理,Direct3D将纹理坐标进行了规范化,使之限定在[0,1]之间。
对于每个3D三角形单元,都可以在纹理中定义一个相应的三角形区域,然后将该三角形内的纹理映射到该3D三角形单元中。另外,为实现该映射,需要在顶点结构Vertex中添加纹理坐标,并且设定相应的顶点格式FVF,如下
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
现在,由3个顶点对象构成的每个三角形都在纹理坐标系中定义了一个相应的纹理三角形。
2. 创建并启用纹理
纹理数据通常从磁盘中的图像文件读入,然后在加载到IDirect3DTexture9对象中。实现这个过程的D3DX函数为D3DCreateTextureFromFile(...),支持的图像格式为BMP、DDS、DIB、JPG、PNG和TGA。创建纹理示例如下
//IDirect3DTexture9 * _stonewall;//创建纹理对象D3DXCreateTextureFromFile(_device, "stonewall.bmp", &_stonewall);//加载纹理图片Device->SetTexture(0, _stonewall);//设置当前工作纹理
SetTexture(DWORD stage, IDiretct3DBaseTexture9 * pTexture)函数用于设置当前工作纹理,stage标识纹理层数—irect3D最多可设置8层纹理,0~7,称为多重纹理),pTexture是纹理指针(为0时表示禁用该层纹理)。
3. 纹理过滤器
当纹理最终被映射到屏幕空间中时,由于纹理三角形和屏幕三角形大小的不一致可能导致显示的图像畸变。为克服这种畸变,使用纹理过滤技术(filtering)。
Direct3D使用三种类型的纹理过滤器,每种过滤器提供一种质量水平,质量越高,开销越大,速度越慢。过滤方式由方法IDirect3DDevice->SetSamplerState来设置。过滤方式有如下三种:
1)最近点采样(nearest point sampling) Direct3D默认过滤方式,处理速度最快,质量最差;
2)线性纹理过滤(linear filtering) 效果好,速度较快;
3)各向异性纹理过滤(anisotropic filtering) 效果最好,速度最慢;
4. 多级渐进纹理
同纹理过滤器一样,我们也可以使用多级渐进链(chain of mipmap)消除尺寸畸变。具体方法是:由某一纹理创建一系列分辨率逐渐减小的纹理图像,并且对每种分辨率下的纹理所采用的过滤方式进行定制,以便保留较为重要的细节。如下图:

多级渐进纹理过滤器主要用于控制Direct3D使用多级渐进纹理的方式。多级渐进纹理过滤器设置函数如下
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, Filter);
其中,Filter可取如下值
D3DTEXF_NONE 禁用多级渐进纹理过滤器
D3DTEXF_POINT 通过使用该过滤器,Direct3D将选择尺寸与屏幕三角形最接近的那一级纹理。一旦选择了某一级纹理,Direct3D就会用指定的放大过滤器或者缩小过滤器对该级纹理进行过滤。
D3DTEXF_LINEAR 通过使用该过滤器,Direct3D将选择尺寸与屏幕三角形最接近的两级纹理级,用指定大小的过滤器进行过滤,然后再将这两级纹理进行线性组合,形成最终的颜色值。
4. 寻址模式
前面说过,纹理坐标被限制在[0,1]之间。但从技术角度还是有问题的。因此,Direct3D定义了4种用来处理纹理坐标超过[0,1]区间的纹理映射模式,分别为重复(wrap)寻址模式、边界颜色(border color)寻址模式、箝位(clamp)寻址模式以及镜像(mirror)寻址模式。
5. 示例
(1)现在总结下为场景添加纹理映射的步骤:
1)构造组成物体的顶点,并为其指定纹理坐标;
2)用函数D3DXCreateTextureFromFile为IDirect3DTexture9接口加载一种纹理;
3)设置缩小过滤器、放大过滤器和多级渐进纹理过滤器;
4)绘制物体前,用函数IDirect3DDevice9::SetTexture来设定与物体相关联的的纹理;
(2)首先,初始化几个全局变量,一个存储四边形顶点的顶点缓存,还有一个是将要映射到该四边形的纹理。
IDirect3DVertexBuffer9 * Quad = 0;IDirect3DTexture9 * Tex = 0;
(3)Setup函数,我们用定义了顶点纹理坐标的两个三角形来构造一个四边形。然后为IDirect3DTexture9接口加载位图文件。接下来调用SetTexture方法启用纹理。最后,我们将缩小过滤器和放大过滤器设为线性过滤模式,并将渐进纹理过滤器设为D3DTEXF_POINT。
bool Setup(){//// 创建顶点缓存//Device->CreateVertexBuffer(6 * sizeof(Vertex), D3DUSAGE_WRITEONLY,Vertex::FVF,D3DPOOL_MANAGED,&Quad,0);Vertex* v;Quad->Lock(0, 0, (void**)&v, 0);//两个三角形的顶点坐标以及纹理坐标//用于构建四边形v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);v[1] = Vertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);v[2] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);v[4] = Vertex( 1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);Quad->Unlock();////创建纹理并设置过滤器//D3DXCreateTextureFromFile(Device,"dx5_logo.bmp",&Tex);Device->SetTexture(0, Tex);Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); //设置放大过滤器为线性Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);//设置缩小过滤器为线性Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);//设置纹理渐进过滤器////不使用光照//Device->SetRenderState(D3DRS_LIGHTING, false);////设置投影矩阵//D3DXMATRIX proj;D3DXMatrixPerspectiveFovLH(&proj,D3DX_PI * 0.5f, // 90 - degree(float)Width / (float)Height,1.0f,1000.0f);Device->SetTransform(D3DTS_PROJECTION, &proj);return true;}(4)Display函数,将当前纹理映射到四边形上,并显示在屏幕中。
bool Display(float timeDelta){if( Device ){Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);Device->BeginScene();Device->SetStreamSource(0, Quad, 0, sizeof(Vertex));Device->SetFVF(Vertex::FVF);Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);Device->EndScene();Device->Present(0, 0, 0, 0);}return true;}本章完。
————Josh 2012年10月27日
- 1楼haihao_4天前 18:02
- 不错,博主加油~