D3D9学习笔记(七) TEXTURE 纹理

texture永远是图形学最精华细节最多的地方,所以我也花了最多的时间阅读和写这个章节。

 

d3dDevice->SetTexture(n,tex)设置当前在n通道的texture,n的数量硬件在0-7.多个通道的texture可以进行blending

 

一个pixel在光照计算后得到一个颜色值c1,它纹理采样有一个颜色值c2,最终这个pixel的颜色值为
Color = c1 x DestBlend+c2 x SourceBlend 
可以通过
IDirect3DDevice9::SetRenderState(D3DRS_BLENDXXX)来控制这个混合策略
默认是
SourceBlend = D3DBLEND_SRCALPHA 
DestBlend = D3DBLEND_INVSRCALPHA
也就是贴图的颜色权重就是alpha值。
可以通过这个设定,设置贴图的透明度,SourceBlend = D3DBLEND_ZERO 
DestBlend = D3DBLEND_ONE就会变成贴图完全消失
 
 
 

 

7.1 address mode

纹理坐标通常在0-1之间,当处理那些不在这个范围内的纹理坐标时的策略就是address mode

IDirect3DDevice9::SetSamplerState(D3DSAMP_ADDRESSU/D3DSAMP_ADDRESSV/D3DSAMP_ADDRESSW,)

D3DTADDRESS_WRAP          重复纹理u=2与u=1相同
D3DTADDRESS_MIRROR        于上类似,但是01正向 12镜像23正向...
D3DTADDRESS_CLAMP        小于0设为0 大于1设为1
D3DTADDRESS_BORDER        超范围的设为设定的border color
(设定这个值通过IDirect3DDevice9::SetSamplerState(D3DSAMP_BORDERCOLOR))
D3DTADDRESS_MIRRORONCE    只镜像一次然后 clamp
 
虽然允许使用任意数值的纹理坐标,但是往往这个值也是被硬件限制的,D3DCAPS9中的MaxTextureRepeat代表纹理坐标的范围在-MaxTextureRepeat到MaxTextureRepeat之间。The interpretation of MaxTextureRepeat is also affected by the D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE capability bit. When this bit is set, the value in the MaxTextureRepeat member is used precisely as described. However, when D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE is not set, texture repeating limitations depend on the size of the texture indexed by the texture coordinates. In this case, MaxTextureRepeat must be scaled by the current texture size at the largest level of detail to compute the valid texture coordinate range. For example, given a texture dimension of 32 and MaxTextureRepeat of 512, the actual valid texture coordinate range is 512/32 = 16, so the texture coordinates for this device must be within the range of -16.0 to +16.0.

7.2 texture filtering

filtering是使用具体的0-1内的纹理坐标获取纹理上颜色值的策略。

IDirect3DDevice9::SetSamplerState0-7),场合参数,filter参数)

场合参数

D3DSAMP_MAGFILTER,一个纹理点(texel)需要被映射到很多pixel的时候放大
D3DSAMP_MINFILTER,一个pixel采样到很多纹理点的时候,放小

D3DSAMP_MIPFILTER mipmap的时候

filter参数

为什么要设置filter,因为D3D采样纹理(直接采样过程)是把0-1的纹理坐标映射到-0.5~n-0.5范围内的纹理像素点(ntexel的像素数)如下图00点和1/3,1/3点的映射像素(左图是pixel表面,右图是纹理图像)分别为(-0.5,-0.5)和(0.5,0.5)(注意0,0位于第一个像素格子的中心)纹理坐标uv对应的texel坐标为(uv)*n-0.5

D3D9学习笔记(七) TEXTURE 纹理_第1张图片

                  

 

这样采样出来看上去就像贴图在pixel表面上比你预计的想左上位移了0.5tixel一样

 

为了解决颜色的错乱(纹理采样的走样),就有了很多种filter策略,这个策略主要在于根据uv得到的texel坐标xy,怎样根据xy找到合适的颜色值

filter参数有:

D3DTEXF_POINT这叫默认的,也是最差的,基本现在都不用的,叫最近点策略,就是采到一个像素点位置(texel)坐标xy时,如果坐标值xy不是整数,那么就转换成离这个浮点数最近的整数,因为整数的texel意味着不需要潜在的平均多个texel的颜色值等,直接取颜色,最快,但是效果可能差别很大。

如最上面的采样结果就会变成这样 D3D9学习笔记(七) TEXTURE 纹理_第2张图片右下的贴图损失了(纹理坐标1,1转化的texel坐标3.5 3.5,转为整数4,4 4,4在贴图处是空白色的)

LINEAR线性差值(其实可以看做二维的模糊),一种效果较好的流行的方式,它对于xy会找到离xy最近的上下左右四个整数值的颜色进行加权平均,颜色基本上最贴近贴图,如上例会变为

D3D9学习笔记(七) TEXTURE 纹理_第3张图片

D3DTEXF_ANISOTROPICtexel映射到曲面物体表面发生的变形叫做anisotropy(各向异性),一个屏幕像素反映射到纹理texel区域的长宽比称为延展度,它反映了anisotropy的程度。

联合LINEARmipmap的方式使用D3DTEXF_ANISOTROPIC可以提高各向异性时的贴图质量,还可以通过IDirect3DDevice9::SetSamplerStateD3DSAMP_MAXANISOTROPY)设置各向异性的degree

 

下面左右分别是使用高低不同质量的贴图,从上到下依次使用线性合并各向异性、线性、最近点的filter模式。可以看到最右下角在低质量贴图时用最近点采样纹理颜色错位严重,而线性是通常可以接受的方式。

     

 

  

7.2.1

MIPMAP

 

1.CreateTexture的第三个参数指定mipmap的level数量,如果设为0,将自动的产生一直降到1*1的所有mip。将usage设为D3DUSAGE_AUTOGENMIPMAP将自动产生mipmap

map

2.设置mipmap的filter以启用mipmap

如SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

 

使用IDirect3DBaseTexture9::SetAutoGenFilterType Method可以设置在自动产生mipmap的时候的filter(怎么由大的贴图生成小的贴图,这个参数同texture filteringtype一样)

使用IDirect3DTexture9::GetSurfaceLevel能够拿到具体某个levelmipmapsurface

使用IDirect3DBaseTexture9::GetLevelCount可以拿到level的数量

  左右两张图分别是开启了mipmap和不开的情况,右图中在图像变小后纹理更加清晰,而左图则使用了低LOD的模式。

 

7.3 texture warpping

理解纹理的warpping(卷曲)就要先看下面一个问题,想把贴图贴给这个立方体然后贴成最下图的样子

 D3D9学习笔记(七) TEXTURE 纹理_第4张图片

如果按照正常的贴图方法,在贴从(0.857)到(0.175)这部分会很难实现,因为对于图中箭头所指的这个面,u坐标从(0.857)到(0.175)进行差值,在贴图上,将跨越4个颜色,而不是结果图中那样的情况。

 

问题的原因在于正常的纹理坐标差值都是基于两个浮点数之间的线性差值,通过设定texture warpping可以解决,当设置了u方向上的warpping后,可以想象将贴图弯曲成一个圆柱了,从(0.857)到(0.175)差值将选择最近的方向,而不是像原来一样跨越四个颜色。

 

设置的函数:

d3dDevice->SetRenderState(D3DRS_WRAP0, D3DWRAPCOORD_0);设置贴图0在u方向warping。
 
D3D在renderstage设置的warpping和7.1采样模式时设置的warpping 是两个不同的概念,要区分

 

 

7.4纹理坐标产生

D3D9学习笔记(七) TEXTURE 纹理_第5张图片

from fvf 是直接从输入的vb中产生,from D3d是自动的产生方式

SetTextureStageStateD3DTSS_TEXTURETRANSFORMFLAGS

D3DTTFF_DISABLE    不对纹理进行坐标变换
D3DTTFF_COUNT1     
D3DTTFF_COUNT2     
D3DTTFF_COUNT3    
D3DTTFF_COUNT4    

The rasterizer should expect (1-4)D texture coordinates. This value is used by fixed function vertex processing; it should be set to 0 when using a programmable vertex shader.

 
D3DTTFF_PROJECTED    每个元素会除以最后一个元素.这个通常联合使用D3DTSS_TCI_CAMERASPACEPOSITION,因为在摄像机空间下的纹理坐标再除以最后一个,得到的纹理坐标就是其剪裁坐标系下的顶点坐标了,这就是投射纹理,即总在视角方向的纹理。在设置这个标记时对于纹理的矩阵设置将不会生效,此时算出来的已经是最终纹理坐标位置了
 

7.4.1自动纹理产生

设置自动纹理产生的方式
IDirect3DDevice9:: SetTextureStageState(D3DTSS_TEXCOORDINDEX
参数:
D3DTSS_TCI_CAMERASPACENORMAL 使用顶点的法向
D3DTSS_TCI_CAMERASPACEPOSITION 使用摄像机空间的顶点位置D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 使用摄像机空间的reflection vector,这个常用于cubic env mapping
D3DTSS_TCI_PASSTHRU 使用VB中的.
这里有一个问题要注意,vb中可以指定顶点的纹理坐标,如D3DFVF_TEX1,在不指定坐标的产生方式时,这只是第0 stage的坐标的产生方式,对于1stage,如果没有指定D3DFVF_TEX1默认是没有纹理坐标的(或者都是00),但此时可用D3DTSS_TCI_PASSTHRU标志告诉stage1也用VB中的D3DFVF_TEX1

7.4.2纹理坐标的变换

IDirect3DDevice9::SetTransform时第一个参数传入D3DTS_TEXTURE0 through D3DTS_TEXTURE7

还要用D3DTSS_TEXTURETRANSFORMFLAGS的非D3DTTFF_DISABLE打开开关

 

7.5 texture blending

首先要查询硬件的IDirect3DDevice9::GetDeviceCaps.是否支持纹理混合

texture可以进行多次混合,每一次混合称为一个stagestage0,开始,最多到7,具体支持的数量还要查询硬件。

 

d3dDevice->SetTexture(0, pTexture1);

d3dDevice->SetTexture(1, pTexture2);

设置stage0 和1的两张贴图,在每个stage进行一次混合然后传入下个stage,下面参数可以控制每个stage的混合方式

IDirect3DDevice9::SetTextureStageStatenD3DTSS_COLOROP/D3DTSS_ALPHAOP..)在第n stage对纹理的哪个颜色通道执行那种混合操作(modulate add。。)

这里的各种参数

D3DTOP_DISABLE                     = 1,
  D3DTOP_SELECTARG1                  = 2,
  D3DTOP_SELECTARG2                  = 3,
  D3DTOP_MODULATE                    = 4,
  D3DTOP_MODULATE2X                  = 5,
  D3DTOP_MODULATE4X                  = 6,
  D3DTOP_ADD                         = 7,单纯的叠加可能会导致过亮
  D3DTOP_ADDSIGNED                   = 8,
  D3DTOP_ADDSIGNED2X                 = 9,
  D3DTOP_SUBTRACT                    = 10,
  D3DTOP_ADDSMOOTH                   = 11,
  D3DTOP_BLENDDIFFUSEALPHA           = 12,
  D3DTOP_BLENDTEXTUREALPHA           = 13,
  D3DTOP_BLENDFACTORALPHA            = 14,
  D3DTOP_BLENDTEXTUREALPHAPM         = 15,
  D3DTOP_BLENDCURRENTALPHA           = 16,
  D3DTOP_PREMODULATE                 = 17,
  D3DTOP_MODULATEALPHA_ADDCOLOR      = 18,
  D3DTOP_MODULATECOLOR_ADDALPHA      = 19,
  D3DTOP_MODULATEINVALPHA_ADDCOLOR   = 20,
  D3DTOP_MODULATEINVCOLOR_ADDALPHA   = 21,
  D3DTOP_BUMPENVMAP                  = 22,
  D3DTOP_BUMPENVMAPLUMINANCE         = 23,
  D3DTOP_DOTPRODUCT3                 = 24,
  D3DTOP_MULTIPLYADD                 = 25,
  D3DTOP_LERP                        = 26,

 

IDirect3DDevice9::SetTextureStageStatenD3DTSS_COLORARG1, component

设定这个纹理混合时的每个混合参数来自什么地方,参数有

D3DTA_CONSTANT

一个常量颜色

D3DTA_CURRENT

当前这个纹理通道已经混合后的结果(如果是第一次混合,那么等于DIFFUSE

D3DTA_DIFFUSE

差值出的当前漫反射颜色

D3DTA_SPECULAR

差值出的当前高光颜色

D3DTA_TEMP

The texture argument is a temporary register color for read or write. D3DTA_TEMP is supported if theD3DPMISCCAPS_TSSARGTEMP device capability is present. The default value for the register is (0.0, 0.0, 0.0, 0.0). Permissions are read/write.

D3DTA_TEXTURE

当前这个纹理通道的纹理

D3DTA_TFACTOR

The texture argument is the texture factor set in a previous call to theSetRenderState with theD3DRS_TEXTUREFACTOR render-state value. Permissions are read-only

 

7.6 MultiPass Texture Blend

某些硬件可能不支持很多个stagetexture blending,这时还可以通过多个pass的渲染来实现,其实就是把一张贴图渲染一遍,不清缓存,再渲染一遍用另外一张贴图...

 

光照贴图

使用贴图可以高效的实现复杂的光照计算,即将顶点的光照计算结果存在贴图中,然后使用贴图的blend multipass

其他

 

IDirect3DDevice9::SetCurrentTexturePalette设置纹理的色板

你可能感兴趣的:(D3D9学习笔记(七) TEXTURE 纹理)