DirectX SDK (August 2008).Direct3D 9.官方指导教程 (五)

Tutorial 5:使用纹理贴图(Using Texture Maps



虽然光照和材质已经使场景更加的真实,但还是没有什么高级显示系统可以比得上表面纹理贴图更加真实。纹理可以想像为热缩包装到表面的墙纸。你可以将木头的纹理贴在立方体上使得立方体看起来就像是木头做的。这里的Texture工程是向第四个教程中的圆柱体贴上香蕉皮纹理,本章包括如何加载纹理、创建顶点、显示贴上纹理的物体。
本教程执行如下步骤进行纹理贴图:
Steps:
Step 1- 定义用户顶点格式(Defining a Custom Vertex Format)
Step 2 – 初始化屏幕几何图形(Initializing Screen Geometry)
Step 3- 显示场景(Rendering the Scene)
Note:Texture工程和Lights工程代码是同一的,除了Texture工程不创建材质或光照,还有其它方面初始化Direct3D、处理消息等在Texture工程中都不涉及。
Step 1定义用户顶点格式(Defining a custom vertex format

在使用纹理之前,用户顶点格式必须使用纹理坐标。纹理坐标告知Direct3D将纹理贴哪个图元顶点上。纹理坐标从0.0变化到1.0,点(0.0,0.0)代表纹理的左上角点,(1.0,1.0)代表右下角。
下面的代码展示了Texture工程中如何设定包含纹理坐标的用户顶点格式。
//一个用户顶点类型结构体,加入了纹理坐标。
struct CUSTOMVERTEX
{
D3DXVECTOR3 position;
//坐标
D3DCOLOR color;
//颜色
#ifndef SHOW_HOW_TO_USE_TCI
FLOAT tu,tv;
//纹理坐标
#endif
};
//可变用户顶点格式(FVF),描述了用户顶点结构体
#ifdef SHOW_HOW_TO_USE_TCI
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#else
#define D3DFVF_CUSTOMVERTEX
(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 )
#endif
关于纹理坐标的更多信息查看(Texture Coordinates(Direct3d9))
现在用户顶点类型已经定义了,下一步是载入纹理和创建圆柱体。
Step 2 初始化屏幕几何图元(Initializing Screen Geometry

在渲染之前,Texture工程调用InitGeometry()函数进行纹理的创建的圆柱体几何图元的初始化工作。
纹理的创建来自于文件夹里的图片,下面的代码片段使用D3DXCreateTextureFromFile()函数创建来自Banana.bamp图片的纹理,将会应用到圆柱体的表面。
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, “Banana.bmp”, &g_pTexture)))
return E_FAIL;
D3DXCreateTextureFromFile()接受的第一个参数是指向将要进行纹理贴图的我Direct3D设备的指针。第二个参数是指向标准类型字符串来指定创建纹理的文件名,在此例中指定Banana.bmp为加载文件第三个参数是指向纹理对象的指针。
当香蕉纹理已经加载并且准备好使用后下一步就开始创建圆柱体,下面的代码使用圆柱体坐标填充顶点缓存。注意第一个顶点都有一个纹理坐标(tu, tv).
for( DWORD i=0; i<50; i++)
{
FLOAT theta = ( 2*D3DX_PI*i)/(50 – 1);
pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta), -1.0f, cosf(theta));
pVertices[2*i+0].color = 0xffffffff;
#ifndef SHOW_HOW_TO_USE_TCI
pVertices[2*i+0].tu = ((FLOAT)i)/(50 -1);
pVertices[2*i+0].tv = 1.0f;
#endif
pVertices[2*i+1].position = D3DXVECTOR3(sinf(theta), 1.0f, cosf(theta));
pVertices[2*i+1].color = 0xff808080;
#ifndef SHOW_SHO_TO_USE_TCI
pVertices[2*i+1].tu = ((FLOAT)I)/(50-1);
pVertices[2*i+1].tv = 0.0f;
#endif
}
每个顶点都包含位置,颜色,和纹理坐标。例子中的代码设定纹理坐标到第一个顶点所以纹理会很平滑的包裹在圆柱体表面。
现在已经加载了纹理并且顶点缓冲也创建了,是准备好开始显示了时候了。
Step 3显示到屏幕(Rendering the Scene

在几何图形初始化结束后是时候显示了,为了将纹理渲染到物体上必须将纹理设定为当前的纹理,下一步是设定纹理舞台状态值。纹理舞台状态允许你定义如何进行纹理的渲染,例如,你可能会将多层纹理进行混合。
在Texture工程中是从设定纹理开始的,下面的代码调用IDirect3DDevice9::SetTexture进行纹理的设定。
g_pd3dDevice -> SetTexture( 0, g_pTexture);
第一个参数是将要设定纹理到哪个舞台的标识符。一个设备环境可以最大设定8个纹理,所以最大值在这是7。在Textuer工程中只有一个纹理并且将他作用到了0号舞台。第二个参数是指向纹理对象的指针。Textuer工程使用已经定义的InitGeometry函数创建好的纹理。
下面的代码通过调用IDirect3DDevice9::SetTextureStageState()方法设定纹理舞台状态参数。
//调整纹理,使用纹理采用纹理舞台状态,将会控制如何将纹理和光照进行协调处理,在这//里调节顶点的纹理和漫射光颜色。
g_pd3dDevice -> SetTexture( 0, g_pTexture);
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_ALPHOP, D3DTOP_DISABLE);
#ifdef SHOW_HOW_TO_USE_TCI
//注意:为了使用Direct3D纹理坐标同时使用舞台状态D3DTSS_TEXCOORDINDEX,如下所
//示,在此全程中使用摄像机空间坐标来生成纹理坐标,TCI参数使用4*4的矩阵进行纹理
//转换,使XYZ TCI坐标生成Tu,tv纹理坐标
//在此例中纹理矩阵将(-1,+1)坐标转换成(0,1)的纹理坐标空间:
//
tu = 0.5*x+0.5
//
tv= -0.5*y+0.5
D3DXMATRIXA16 mat;
mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f;
g_pd3dDevice -> SetTransform( D3DTS_TEXTURE0, &mat);
g_pd3dDevice _. SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTTFF_COUNT2);
g_pd3dDevice ->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX,
D3DTSS_TCI_CAMERASPACEPOSITION);
#endif
IDirect3DDevice9::SetTextureStageState()的第一个参数是舞台索引进行变量设定,在例子中改变了0号舞台的纹理值,所以这里使用0,下一个参数是要设定的纹理状态,更多关于纹理状态的参数信息可以看D3DTEXTURESTAGESTATETYPE.下一个参数是哪一个纹理状态将进行设定,在这里的值根据你已经指定过的纹理舞台状态值来设定。
在为每一个舞台状态设定了期望值之后,圆柱体就可以用纹理进行渲染了。
使用纹理的坐标的另一种方法是自动生成它们。这里已经使用纹理坐标索引进行完成了。TCI使用纹理矩阵将(x,y,z)来源坐标转换为(tu,tv)的纹理坐标。在Texture工程中顶点的摄像机空间坐标应用到纹理坐标。
第一步是创建将要进行用来转换用的矩阵如下代码所示:

D3DXMATRIX mat;

mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;

mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;

mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;

mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f;
在创建完成矩阵之后必须调用IDirect3DDevice9::SetTransform()如下所示
g_pd3dDevice ->SetTransform( D3DTS_TEXTURE0, &mat);
D3DTS_TEXTURE0标记告知Ddiect3D应用转换过的纹理到0号纹理舞台,下一步是设定更多的纹理舞台数据以达到期望的效果,如下所示:
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMAFLAGS,
D3DTTFF_COUNT2);
g_pd3dDevice -> SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX,
D3DTSS_TCI_CAMERASPACEPOSITION);
现在纹理坐标已经设定,已经准备好进行场景的绘制了。注意纹理坐标自动生成到圆柱体,这种特殊的机制可以使纹理在几何图元显示完成后进行纹理的显示。
关于更多Textures的信息在Direct3D Textures(Direct3d9)

posted @ 2009-09-17 12:14  Maxice  阅读(966)  评论(0编辑  收藏  举报