Basic Texturing(基本纹理技术)

来源:互联网 发布:巨人网络校园招聘2017 编辑:程序博客网 时间:2024/04/28 03:54
这几天一直都在看baisc texturing ,这一节写的是太精彩了,原本只是了解大致原理,细节基本很模糊的我,居然对texturing有了比较清晰的理解。为了帮助我更好的理解,我有必要写点读书笔记。

我们知道,通过光照计算和设置材质属性,我们可以为每个顶点计算一个颜色值;利用vetex shader,我们可以扩展固定流水线的功能,并且可以每个顶点随意计算其颜色值。利用这两种方法建模的颜色值,能够通过光栅器插值到屏幕中对应的像素中。但是,仅仅通过这两种方法,很难为物体做一个非常精细的“面孔”,所以就引入了Texturing 技术。

    纹理化技术,能把一张很复杂的图片绘制在物体的表面,它也可以允许我们为每个像素建立一张漫反射表,其索引可以通过每个对应被插值的顶点的纹理坐标计算得到。纹理的每个元素就好比对应一个像素,都是一个color。纹理坐标一般是有一维,两维,三维和四维。把查询漫反射表的结果与光栅化的结果混合起来,能产生一个漫反射颜色,一起送给frame buffer。当然,它也能支持multi texturing,每个texturing stage 的output 也就是下一个stage的input。

    固定功能的像素处理通过multi texturing 各个stage来产生丰富的颜色。可编程的pixel shader,当然就非常灵活的产生颜色了。

    现在主要有三种纹理资源,矩形纹理,立方体纹理以及大体积纹理(volume)。在这一章讨论了纹理资源的接口以及纹理资源的管理,并且详细的解释了纹理坐标的处理(非常精彩)。

   纹理坐标是由vertex buffer提供的或者由direct3d自动产生。在提交到teuring stage之前,纹理坐标能通过矩阵进行变换。不过,一旦纹理坐标绑定到一个源像素,这个纹理就会与一个stage绑定。这一章详细讲解了纹理采样技术,使用不同的纹理采样方法,将会得到不同的效果。

 

纹理坐标的处理

  理论上纹理坐标值范围在【0,1】,如线性纹理和矩形纹理。但是立方体纹理有点不一样,它的值范围是在【-1,1】,而且它的每个面上的纹理值都有一个值是-1或者1,其立方体的中心是其(0,0,0)位置。

 在顶点被转化到屏幕空间后,光栅将其纹理进行插值,这样就可以计算出来一个像素上纹理坐标的变化值。如果把这个变化值乘以纹理的分辨率,就可以得到一个像素对应多少个纹理像素。利用这个信息,我们就可以选择mipmap level。

   但是很多时候,我们需要直接将纹理像素值映射到屏幕中去,如用户界面。为了取得一对一的效果,primitive的位置相对屏幕空间位置得偏移0.5,这是因为三角形的光栅化规则,整数坐标位置是像素的中心位置,这个偏移可以使三角形位置正好对应于像素位置,这种效果可以很容易通过变换后顶点实现,因为它们的坐标已经是屏幕空间的坐标了。详细解释可以参考 DirectX SDK document ("Mapping Texels to Pixels")。

   顶点可以携带多组纹理坐标,默认第一组对应texturing的第一个阶段。TSS Tex Coord Index可以用来控制哪个stage 使用哪组坐标。

   Direct3D也会自动为顶点产生纹理坐标。

   纹理坐标也可以通过变换矩阵进行转换,转换矩阵一般是一个4*4矩阵的左上方的子矩阵,它的维度取决于纹理的维度和TSS Texture Transform Flag。

纹理寻址

   虽然纹理坐标一般是在【0,1】区间,但是你同样可以使用这个范围之外的纹理值,如(2,3)。D3DCAPS的MaxTextureRepeat 可以设置设置纹理区间的范围,比如如果这个值是5,设备支持的纹理坐标的区间就是【-5,5】。如果TextureCaps 的D3DTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE没有被设置,在进行插值之前设备将纹理坐标放大到纹理的实际尺寸,MaxTexureRepeat 实际上指定了坐标放大后能被设备支持的范围。

在单位区间之外的纹理坐标处理方式是通过纹理的寻址模式设置的,寻址模式包括Wrap, Mirror,Clamp,Border,MirrorOnce。默认是Wrap模式。

纹理 Wrapping

纹理wrapping是用于调节光栅器对纹理坐标进行插值的方式,注意千万不要将纹理的Wrapping 与寻址模式wrap 混为一谈,纹理wrapping 是通过每个stage的 render state的 RS wrap 0到RS wrap 15。启用wraping,光栅器插值就会采用纹理空间两个个坐标的最短路径的方法来实现,这里纹理空间被视为一个无限重复的网格。

纹理采样

纹理采样就是为每个像素选取纹理像素的操作。如果在一个像素对应的纹理空间尺寸是2的幂,并且也有一个miplevel 的纹理与它对应,这个时候采样能直接从这个miplevel的纹理采样。但是大多数时候,一个像素所对应的纹理像素空间不是2的幂。Direct3D 提供了3种纹理stage state来控制纹理的采样:SS Min Filter(纹理被缩小), SS max Filter(纹理被放大), SS Mip Filter(纹理被Mipmap)。这三种状态都可取值于D3DTEXTUREFILTERTYPE(D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC, D3DTEXF_FLATCUBIC, D3DTEXF_GAUSSIANCUBIC)。 在缩小化过程中,SS Min Filter将指定几个纹理像素怎么样合成一个像素值。 在放大过程中,SS Max Filter 怎么样插值纹理样例。除了只从一个纹理的mip level 取样外,我们可以从两个相邻的mip level取样,用SS Mip Filter来合成它们,用这种方法,当基本元素在场景里面移动或者纹理缩小量和放大量变化的时候,能产生比较平滑的过渡。

 

并不是所有的D3DTEXTUREFILTERTYPE的值都能应用到这三种状态。 D3DTEXF_POINT 和 D3DTEXF_LINEAR 能所有这三种状态, D3DTEXF_NONE 能被用于禁止mipmap。 D3DTEXF_ANISOTROPIC能被用于放大与缩小,然而,D3DTEXF_PYRAMIDALQUAD和D3DTEXF_GAUSSIANQUAD只能用户放大过滤。

点过滤选择离像素对应的纹理坐标最近的纹理像素或者mip map level。线性过滤,当用于放大与缩小的时候,选择相邻的四个纹理像素,用纹理坐标进行线性插值来获得,当用于mip level的时候,选择相邻的两个mip level,从他们之间采取线性插值采样。在线性mip level 插值的时候,先分别通过缩小和放大来取得采得连个mip level的样。 立方体过滤器提供更加精确的采样,他们通过3*3 相邻像素进行线性插值。

Anisotropic过滤可以用于非正方形区域的纹理采样。

纹理阶段处理

当一个纹理被地址化和被采样以后,纹理像素值就会产生。这个纹理像素值可以结合其他的input在一个纹理stage中来为像素产生一个新的diffuse颜色值。这个diffuse 能被传递到下一个Stage进行进一步的处理。每一个纹理stage处理包括一个RGB单元处理和一个alpha单元处理。这两个单元处理在direct3D中是独立的,串联起来的。你要分别设置这两个单元的状态。每个单元处理能从6个输入通道中选择3个作为它的参数。这两个单元处理后的结果也能够被送到两种可能目的地(Current, Temp)之一做进一步的处理。

6个输入通道包括:来自光栅器的被插值的diffuse , 来自光栅器的被插值的specular, 当前纹理取样的纹理像素,RS Texture Factor 值,前一个纹理Stage的结果和临时纹理stage寄存器里面的内容。这里的每个输入都有一个值与之对应。D3DTA_SELECTMASK可以用来选择这6个输入通道。

RGB 和alpha处理单元都能够计算多达3个参数的函数。每个参数都绑定到一个输入通道。 TSS Color Arg 0, TSS Color Arg1, TSS Color Arg2, TSS Alpha Arg 0 , TSS Alpha Arg 1, TSS Alpha Arg 2,分别代表各个参数。 TSS Color Op 和 TSS Alpha Op表示对应的函数。TSS Result Arg 指定输出结果。