纹理映射(Texture Mapping)

时间:2022-09-10 18:49:23

当DirectxD 渲染图元,必须将坐标变换到二维屏幕。从纹理中为每个像素获取颜色过程,就是纹理过滤(texture filtering)。而屏幕显示图形大小和纹理贴图大小是不同的。这样纹理就会被放大或者缩小。如何将多个纹理元素的颜色融合到一个像素就取决于纹理过滤方式

4种纹理过滤方式:

最近点采样过滤( nearst-pointsampling): 

最近点采样,不进行任何过滤操作的速度最快也最简单,只是针对每一个象素对最接近它的纹理单元进行采样,可用于上面两种情况。但是这种纹理过滤方法的效果最差,在屏幕显示的图像会显得十分模糊。

      //       g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_POINT);  
      //       g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_POINT);  

线性纹理过滤( lineartexture filtering): 

线性过滤也比较简单,每个象素要对最接近它的2 x 2的纹理单元矩阵进行采样,取4个纹理单元的平均值,也可用于上面的两种情况。这种纹理过滤方法的效果比上面的要好很多。
这是一种较好的材质影像插补的处理方式,会先找出最接近像素的四个图素,然后在它们之间作差补效果,最后产生的结果才会被贴到像素的位置上,这样不会看到“马赛克”现象。

           g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);  
            g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);  

多级渐进过滤(texturefiltering with mipmaps)

三线性过滤相对的比较复杂,它只能用于纹理被缩小的情况,需要先构造纹理图像的mipmap,mip的意思是“在狭窄的地方里的许多东西”,mipmap就是对最初的纹理图像构造的一系列分辨率减少并且预先过滤的纹理图。对于一个8 x 8的纹理来说需要为它构造4 x 4、2 x 2、1 x 1这三个mipmap。如果正方形被缩小到在屏幕上占6 x 6的象素矩阵,一个象素的采样过程就变成这样,首先是到8 x 8的纹理图中进行对最接近它2 x 2的纹理单元矩阵进行采样(也就是上面的线性过滤);其次是到4 x 4的纹理图中重复上面的过程;接着把上面两次采样的结果进行加权平均,得到最后的采样数据。可以看出整个过程一共进行了三次的线性过滤,所以这种方法叫做三线性过滤,它的效果是三种纹理过滤方法里面最好的。

   //       g_pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);  
   //       g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAXMIPLEVEL, 16);  

各项异性过滤(anisotropictexture filtering)

在很多时候,三维物体的表面不可能是完全平面的,当三维物体的表面和投影平面不平行时,它在屏幕上的投影会有拉长和扭曲的现象,这种现象称为各向异性(Anisotropic)。当一个各项异性的图元映射到纹理元素上时,它的形状就会发生扭曲。而Direct3D会根据屏幕像素反向转换到纹理元素的延长度,来决定各项异性的程度。

各向异性过滤是最新型的过滤方法,它需要对映射点周围方形8个或更多的像素进行取样,获得平均值后映射到像素点上。对于许多3D加速卡来说,采用8个以上像素取样的各向异性过滤几乎是不可能的,因为它比三线性过滤需要更多的像素填充率。但是对于3D游戏来说,各向异性过滤则是很重要的一个功能,因为它可以使画面更加逼真,自然处理起来也比三线性过滤会更慢。

      g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAXANISOTROPY, 3);  
      g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);  
      g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);  

4大纹理寻址方式:

重复寻址:重复原来纹理

镜像寻址: 在每个整数纹理坐标连接处自动复制并翻转纹理

夹取寻址 对于[0,1]之外的内容,讲边缘内容沿U,V进行延伸

边框颜色纹理寻址:周围黑色


纹理映射4步法:

 
//顶点的定义                 
struct CUSTOMVERTEX    
{   
      FLOAT_x, _y, _z;               // 顶点的位置   
      FLOAT_u, _v;                   // 纹理坐标   
      CUSTOMVERTEX(FLOATx, FLOAT y, FLOAT z, FLOAT u, FLOAT v)   
              :_x(x), _y(y), _z(z), _u(u),_v(v) {}   
};   
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)   
     
//顶点的访问                      
//填充顶点缓存   
              CUSTOMVERTEX*pVertices;   
              if(FAILED(g_pVertexBuffer->Lock( 0, sizeof(CUSTOMVERTEX),(void**)&pVertices, 0 ) ))   
                     returnE_FAIL;   
              //填充数据   
              pVertices[0]=CUSTOMVERTEX(-10.0f,  10.0f, -10.0f,0.0f,0.0f);   
              pVertices[1]= CUSTOMVERTEX(10.0f,  10.0f, -10.0f,1.0f, 0.0f);   
              pVertices[2]= CUSTOMVERTEX(10.0f, -10.0f, -10.0f, 1.0f, 1.0f);   
              pVertices[3]=CUSTOMVERTEX(-10.0f, -10.0f, -10.0f, 0.0f, 1.0f);   
g_pVertexBuffer->Unlock();   
    

// 纹理的创建    
LPDIRECT3DTEXTURE9      g_pTexture   = NULL;  // 纹理接口对象   
D3DXCreateTextureFromFile(g_pd3dDevice,L"pal5q.jpg",&g_pTexture); // 创建纹理   
 
// 纹理的启用   
g_pd3dDevice->BeginScene();                    
    
g_pd3dDevice->SetTexture(0,g_pTexture);   
    
/*纹理设置完之后,就开始绘制,用DrawIndexedPrimitive,DrawSubset 之类的函数*/   
g_pd3dDevice->EndScene();                       // 结束绘制   


在纹理启用之前,可以设置纹理状态,寻址,过滤等

    // 设置材质  
    D3DMATERIAL9 mtrl;  
    ::ZeroMemory(&mtrl, sizeof(mtrl));  
    mtrl.Ambient  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);  
    mtrl.Diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);  
    mtrl.Specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);  
    g_pd3dDevice->SetMaterial(&mtrl);  
  
    // 开始设置渲染状态  
    g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);   //开启背面消隐  
    g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f)); //设置环境光  

  // 设置重复纹理寻址模式  
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);  
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);  
  
    //各向异性过滤  
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 3);  
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);  
    g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);  
  
    //线性纹理过滤  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);  
  
    // 最近点采样过滤  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);  
  
    // 渐进纹理过滤  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);  
    //      g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 16);  



参考

blog.csdn.net/poem_qianmo/article/details/8567848

blog.csdn.net/sharp2wing/article/details/5683379