3D游戏编程入门(十九)给模型帖制纹理
呼,好累啊,不知怎么的,近来一直比较疲惫,总想睡觉>_<果然是人又变懒了么。
还是继续复习好了,学着学着就能学进了。恩,我们实现了立方体的绘制,并且给它矩阵让它能够变换了,今天我们开始给它帖上纹理。
纹理
概念方面
首先我们来了解一下纹理是什么东西。其实纹理就一个二维的位图,说的再俗些那就是个图啦,我们把它贴到物体模型表面,让它看起来有颜色,图案。
纹理位图,是一个二维数组,数组中每一项都是一个颜色值,又称为纹理元素。bmp,tga,png这些后缀名的文件都可以做纹理位图。
纹理位图细节说明
我们电脑里一定不少好图图,特别是现在的五花八门桌面壁纸,但我们不建议直接使用它,因为计算机内存管理是以32字节为一个单位的原因,边长为2的n次方象素更适合我们的边长进行读取,例如64X64,128X128,256X256之类的正方形更好,正方形会在我们进行顶点变换时不易发生压挤变形。
纹理在渲染时是占用系统资源最大的部分,我们需要尽量可能的使用比较小的渲染纹理,而且我们需要知道,纹理在我们内存中存储时,系统会自动将其除以2后再进行备分储存。例如吧,我们的一个32X32的纹理,在内存中并非仅仅存储一个位图,还会存储16X16,8X8,4X4,2X2,1X1这样的5张逐步递减的图,为什么系统要这样做呢?一会我们将参数和多重纹理的时候就清楚咯。
UV图
学过3D MAX的朋友或许会有我一样的痛苦,展UV和做骨骼动画是最痛苦的事情了。而当时我并不知道UV是做什么用的,现在我们可以清楚咯,它是记录我们的纹理坐标的。我们的任何一个纹理图,都被定义为:其x轴水平方向为U,y轴垂直方向为V,而U和V的取值我们通常是限制在一个0到1之间的范围的(个别时候可以取1以外的值来实现特效)。UV分别代表占宽高的百分比,我们定义图的左上角UV为(0,0),右下角为(1,1)。
纹理映射
将纹理的元素地址转换成对象模型上的点坐标,这个过程就是纹理映射。
我们进行纹理绘制的过程
- 从程序外界载入纹理
- 分配纹理顶点坐标
- 设置当前的渲染纹理
- 设置纹理的渲染状态
- 渲染顶点缓冲区
首先,载入纹理,先创建一个纹理的对象IDirect3DDevice9::CreateTexture()
之后我们将文件载入纹理对象中。这步和上一步可以合并起来,使用d3dx9.lib中的库函数,
D3DXCreateTextureFromFile(
LPDIRECT3DDEVICE9 pDevice, //D3D设备指针
LPCTSTR pSrcFile, //纹理图的相对路径和文件名
LPDIRECT3DTEXTURE9 * ppTexture //传出的D3D纹理接口指针
) ;
之后我们分配顶点纹理坐标,再此之前,我们要重新设置我们的顶点灵活格式,因为我们的顶点不再是仅仅存放一个坐标一个颜色了,还需存放纹理的UV值,所以我们需要位或上D3DFVF_TEX1,在其结构声明中也需要加入float u,v,当然也要为其赋值。
分配完毕纹理顶点坐标,我们需要对当前渲染的纹理进行设置,设置渲染纹理的函数声明如下:
HRESULT SetTexture(
DWORD Stage, //多级纹理的索引,从0-7,单层纹理取0
IDirect3DBaseTexture9 *pTexture //Direct3D的纹理接口指针
);
这里我们暂时Stage设置为0,之后我们再说多重纹理时再对其详细说明。第二个参数是纹理接口指针,我们在第一步载入纹理时候,函数会为我们传出的。
告诉了电脑我们使用哪块纹理之后,我们需要设置纹理的渲染状态。
HRESULT SetTextureStageState(
DWORD Stage, //当前设置的多级纹理的索引
D3DTEXTURESTAGESTATETYPE Type, //纹理渲染状态的类型
DWORD Value //纹理渲染状态的值,与类型相对应
);
其中第一个参数依旧设0代表0号纹理,第二个参数可以选择20多个宏定义,我仅仅介绍部分重要的吧
- D3DTSS_COLOROP 代表颜色渲染开始
- D3DTSS_COLORARG1 代表1号颜色渲染
- D3DTSS_COLORARG2 代表2号颜色渲染
- D3DTSS_ALPHAOP 代表ALPHA通道渲染开始
- D3DTSS_ALPHAARG1 代表1号ALPHA通道渲染
- D3DTSS_ALPHAARG2 代表2号ALPHA通道渲染
第三个参数代表渲染状态的值,它是和第二个参数相对应的,恩,这里是相当麻烦的,我还是举例说明吧
一般来说,我们先设置颜色渲染的开始
SetTextureStageState( 0,D3DTSS_COLOROP, D3DTOP_ADD );//代表,从这里开始向下是纹理颜色部分的渲染,并且进行ADD,将下面的纹理进行相加。
SetTextureStageState( 0,D3DTSS_COLORARG1, D3DTA_TEXTURE);//ARG1代表这是第一个需要相加的纹理,并且它是一个普通的纹理结构,属于默认值
SetTextureStageState( 0,D3DTSS_COLORARG2, D3DTA_CURRENT);//ARG2代表这是第二个需要相加的纹理,由于它也是默认值,我们不需要对此纹理进行特殊处理。若我们将这里的第三个参数换为D3DTA_DIFFUSE则代表此纹理的颜色是作为漫射光的纹理使用的。
灯光我们下次再说,这里大家做个简单了解就可,以后还会更详细的进行说明。 其他的明天再写吧。今天晚上看传奇2的代码看的我头晕,呼呼~