XNA Shader编程教程3.1-纹理
纹理就是3D模型外表面的图案,本质是把平面图形贴到3D物体表面上,XNA支持bmp、jpg、tga、png、dds格式的图片。纹理的x、y坐标一般称为Tu、Tv,坐标原点在纹理图片的左上角,向右为Tu轴正方向,向下为Tv轴的正方向,无论纹理图片的大小,纹理坐标范围都为0.0到1.0,即所有纹理图形的右下角的Tu、Tv坐标为(1.0,1.0)。例如3D模型的一个正方形表面为一矩形,其左上角、右上角、左下角、右下角4个顶点的纹理坐标分别是:(0,0)、(1,0)、(0,1)、(1,1),则表示要将图片的所有部分都贴到这个矩形表面,如纹理坐标分别为(0,0)、(0.5,0)、(0,0.5)、(0.5,0.5),则表示将图片的左上角四分之一部分贴到这个矩形表面。
要在XNA中实现纹理,可在shader文件中加入如下代码:
texture modelTexture; //纹理变量 sampler ModelTextureSampler = sampler_state //纹理采样器 { Texture = <modelTexture>; //纹理采样器使用的纹理对象 MinFilter = Linear; //缩小图形使用线性滤波 MagFilter = Linear; //放大图形使用线性滤波 MipFilter = Linear; //Mipmap使用线性滤波 AddressU = Wrap; //U、V方向上的纹理寻址模式都采用Wrap方式 AddressV = Wrap; };
纹理过滤
过滤是指通过给定的uv坐标从纹理贴图中获取图素的一种方法,Direct3D提供3种纹理过滤方法和所谓的“mipmap”(MIP是拉丁语“multum in parvo”的缩写,可以解释为“many things in a small place”小中见大、小型而内容丰富),3种纹理过滤方法是:
- 最近点采样
- 线性纹理采样
- 各向异性(anisotropic)
纹理过滤应考虑两种不同的情况:放大(magnification)和缩小(minification)。举例来说,将一张64×64的纹理映射到一个400×400像素的多边形时,便会发生放大,这会导致“锯齿”。而将一张64×64的纹理映射到一个10×10像素的多变形时,缩小会导致“像素抖动”,看上去使人晕眩。
Mipmap由一系列纹理组成,其中每张纹理是一张分辨率逐渐降低的图像,每一级的高度和宽度都是前一级的高度和宽度的一半,使用mipmap可以确保无论是靠近还是远离纹理,纹理都可以保持它原有的真实性和质量,从而减少了放大和缩小带来的负面效果。
大多数硬件都支持4种不同的过滤:点采样、双线性过滤(Direct3D中称之为线性过滤)、三线性过滤(Direct3D中称之为“线性过滤+mipmap”)、各向异性过滤。
从上面的代码可知我们使用的是三线过滤。
纹理寻址模式
代码中的“AddressU = Wrap; AddressV = Wrap;”称为纹理寻址模式(texture-addressing mode)。当顶点的纹理坐标设置在0到1之间,以此来选择一张纹理贴图不难理解。但如果给出的纹理坐标超出了这个范围会如何?这取决于所选择的纹理寻址模式。有几种不同的寻址模式(以下例子中的纹理坐标都是(0,0)、(3,0)、(0,3)、(3,3):
1.包装(wrap):在纹理坐标的每个整数相接处重复纹理,这也是默认模式,如图:
2.镜像(mirror):在每个整数边界对纹理做一次镜像。
3.夹持(clamp):只将纹理应用到多边形上一次,然后对超出部分涂上纹理边缘像素的颜色。
还有边框颜色(border color)和一次镜像(MirrorOnce)不是很常用。
在纹理上应用漫反射和镜面反射
然后在pixelSahder加入以下代码:
float4 textureColor = tex2D(ModelTextureSampler, TexCoord); return vAmbient +textureColor;
程序截图如下:
如要在纹理上加上漫反射光照,代码应变为 :
return vAmbient +textureColor*vDiffuseColor * Diff;
程序截图如下:
如要再加上镜面高光,代码应变为:
return vAmbient + textureColor*(vDiffuseColor * Diff + vSpecularColor * Specular);
程序截图如下:
本程序可以通过按空格键在三种不同方式间切换,详情请见源代码。
发布时间:2009/4/10 上午11:08:02 阅读次数:13979