【Visual C++】游戏开发笔记四十一 浅墨DirectX教程之九 为三维世界添彩:纹理映射技术(一)
本系列文章由zhmxy555(毛星云)编写,转载请注明出处。
文章链接: http://blog.csdn.net/zhmxy555/article/details/8523341
作者:毛星云(浅墨) 邮箱: happylifemxy@163.com
本篇文章里,我们对Direct3D之中固定功能流水线中的纹理映射相关的知识进行了详尽的剖析,文章末尾依旧是提供文章配套详细注释的demo源代码的欣赏,并在文章末尾给出了源代码的下载地址。由于纹理映射相关知识体系比较繁杂,所以需要分次进行介绍,此为上篇。
一、引言
江山如此多娇,风景如画。万物都有其独特的特点。真实世界中的物体,在计算机三维世界中如果单单用各种各样的几何体以及顶点坐标,顶点颜色来模拟的话,往往缺乏生机,往往差强人意。
比如说我们要绘制出如下效果的一个贴了瓷砖的立方体:
综合我们之前讲过的知识,绘制一个立方体是小菜一碟。但关键就来了,如何绘制出像砖块那样坑坑洼洼的效果呢?难不成用成千上万的顶点坐标一个个去机械的模拟?这显然不现实。
相信正确的做法大家应该很容易想到,先绘制一个立方体,接着准备一副描绘着砖块状的2D图片,然后把这幅图片像贴画一样贴到这个立方体的六个面,这样绘制砖块立方体的效果就可以实现了。
其实上面我们讲到的这种方法,就是计算机图形学中“纹理映射”这套技术思想的真实写照。
在我们的计算机三维世界中,想要模拟出真实而复杂的三维物体,让他们从表面上看起来逼真,就需要请出“纹理映射”这套技术。
二、纹理映射的概念
一言以蔽之,纹理映射是一种将2D图像映射到3D物体上的技术。
一般来说,纹理是表示物体表面细节的一副或者几幅二维图形,也称纹理贴图(texture)。当我们把纹理按照特定的方式映射到物体表面上的时候,能使物体看上去更加真实。在当今流行的计算机图形系统中,纹理绘制已经成了渲染方法中的中流砥柱了。
想要理解纹理映射其实非常简单,把纹理看做是应用在物体表面上的像素颜色就可以了。
在真实世界中,纹理表示一个对象的颜色、图案或者触觉特性。但在计算机图形学中,纹理只表示对象表面的彩色图案,它不能改变对象的几何形式,换言之,就像贴在几何体表面上的贴画一样。
好了,基本概念应该讲明白了,下面我们来看看如果要使用这种纹理映射技术的话,需要了解的具体知识。
三、纹理映射使用四步曲
这一小节里面我们详细讲解了使用纹理映射的具体细节。
1. 纹理映射使用四步曲之一,纹理坐标的定义
我们一般把纹理映射所使用的2D图像称作纹理贴图。Direct3D支持多种的纹理贴图,比如有.bmp、.dds、.dib、.png以及.tga等等.虽然说Direct3D对纹理贴图的大小没有限制,但是为了提高程序使用纹理的效率,通常使用边长为2的N次方幂的正方形图片,比如128 x128,256 x 256,512 x 512等等。
纹理贴图往往都通过一个二维数组存储每个点的颜色值,该颜色值被称作纹理元素,而每个纹理元素在纹理中都有唯一的地址。而为了将纹理贴图映射到三维图形中,Direct3D使用了纹理坐标确定纹理贴图上的每个纹理元素。
纹理坐标由一个二维坐标系指定,这个坐标系由沿水平方向的u轴和沿垂直方向的v轴构成,他们两个合起来就是坐标对(u,v),其实和我们习惯的(x,y)坐标对是一个概念,只不过在纹理贴图中我们习惯用(u,v)而已。其中u轴正方向为水平向右,v轴正方向为垂直向下,且他们的取值范围都在[0,1]之间。
纹理坐标位于纹理空间之中,是相对坐标,相对于纹理坐标系中的原点(0,0)。当把纹理贴到三维模型表面上时,纹理元素首先被映射到物体模型的局部坐标系中,然后再变换到屏幕坐标系中对应像素的位置处。
另外的一点,纹理坐标是通过纹理层和纹理联系到一起的,通常情况下只需使用一层纹理就够了。记得我们原来讲FVF灵活顶点格式的时候讲到过,一个灵活顶点格式中允许最多定义八组纹理坐标,而每组纹理坐标都对应一个纹理层,这就是说每个顶点最多可以使用八层纹理。
比如这样写:
HRESULT D3DXCreateTexture( __in LPDIRECT3DDEVICE9 pDevice, __in UINT Width, __in UINT Height, __in UINT MipLevels, __in DWORD Usage, __in D3DFORMAT Format, __in D3DPOOL Pool, __out LPDIRECT3DTEXTURE9 *ppTexture);
■ 第一个参数,LPDIRECT3DDEVICE9类型的pDevice,无需多言,这就是我们的绘制金钥匙——Direct3D设备对象了。
■ 第二个参数,UINT类型的Width,表示我们创建的纹理对象的宽度。
■ 第三个参数,UINT类型的Height,表示我们创建的纹理对象的高度。
■ 第四个参数,UINT类型的MipLevels,表示我们创建的纹理的渐进级别,通常取默认值D3DX_DEFAULT就可以了,表示创建一个完整MIP贴图链。。其实取0也无妨,和取默认值D3DX_DEFAULT效果是一样的。
■ 第五个参数,DWORD类型的Usage,指定了我们纹理的使用方式,取值在0、D3DUSAGE_RENDERTARGET、D3DUSAGE_DYMANIC中三取一。
■ 第六个参数,D3DFORMAT类型的Format,用于指定纹理中每个保存每个颜色成分所使用的位数,在D3DFORMAT枚举体中取值,这个参数也可以设为0,表示使用默认值。
■ 第七个参数,D3DPOOL类型的Pool,指定了纹理对象停驻的内存的类别,在D3DPOOL枚举体中取值,不过我们经常是在这个枚举体其中的两个成员D3DPOOL_DEFAULT和D3DPOOL_MANAGED之间取一个。
■ 第八个参数,LPDIRECT3DTEXTURE9类型的*ppTexture,指针的指针,也就是指向IDirect3DTexture9接口的地址,显然我们调用D3DXCreateTexture,就是把最终创建的纹理交给这个参数保管了,后面如果要使用我们创建的这个纹理的话,通过这个参数就可以了。
但更多情况下我们是从文件中读取纹理图形的,我们可以任意读取我们喜欢的图片文件到Direct3D中,这就用到
好了,美图看完了,继续来学习吧。另外提一点,《仙剑奇侠传五前传》就是用我们目前正在学习的DirectX 9.0c配合RenderWare游戏引擎来进行研发的,所以为了振兴国产游戏,大家共同努力学习吧~
4.纹理映射使用四步曲之四,纹理的启用
加载完纹理后,就可以调用IDirect3DDevice9接口的SetTexture方法,设置我们当前需要启用的纹理。我们可以在MSDN中查到SetTexture方法有如下原型:
大家可以发现,这是《仙剑奇侠传五前传》中可控角色之一凌波的2D头像,浅墨非常喜欢这个痴情的角色的。
好了,废话不多说,我们贴出源代码:
文章最后,依旧是放出本篇文章配套源代码的下载:
本节笔记配套源代码请点击这里下载:
【浅墨DirectX提高班】配套源代码之九下载
其中图标素材依旧是上面用到的仙五前传中的凌波
以上就是本节笔记的全部内容,更多精彩内容,且听下回分解。
浅墨在这里,希望喜欢游戏开发系列文章的朋友们能留下你们的评论,每次浅墨登陆博客看到大家的留言的时候都会非常开心,感觉自己正在传递一种信仰,一种精神。但是有时候你们的评论太多了,浅墨一一回复不过来,在这里给大家说声抱歉~~
文章最后,依然是【每文一语】栏目,今天的句子是:
我们会觉得焦虑,无非是因为现在的我们,跟想象中的自己,很有距离。打败焦虑的最好方法,就是去做那些让你焦虑的事情。不要问,不要等,不要犹豫,不要回头,既然你认准了这条路,就不要去打听要走多久。电脑屏幕前的各位朋友,早安~
下周一,让我们离游戏开发的梦想更近一步。
下周一,游戏开发笔记,我们,不见不散。