• 热门专题

Directx11教程(31) 纹理映射(1)

作者:迈克老狼2012  发布日期:2012-04-10 13:04:22
Tag标签:Directx11  纹理映射  
  •         在前面的例子中,我们要么是直接给顶点赋颜色值,要么是在顶点属性中设置Diffuse和Specular系数,从而根据光照参数计算得到物体表面颜色,但这样得到的颜色真实感要差很多。如果我们直接把一副图像映射到三角形面上,从而得到物体表面颜色值,效果会好很多,比如下面的两幅图,右边的图是把一副图片映射到2个三角形上。

    image

     

         甚至,我们还可以直接使用图像的颜色值做为顶点(或者pixel)的diffuse值,融合光照计算公式,得到最终的表面颜色值,这样会有更好的效果。

     

         通常,我们把图像映射到三角形面上的技术称作纹理映射(texture mapping)。在纹理映射过程中,我们使用纹理坐标的方式(或称u、v坐标),把纹理进行划分,如下图,假设图像为256*256像素,则左上角纹理坐标为(0,0),右上角为(1,0),左下角为(0,1),右下角为(1,1)。

     

        之所以使用这种归一化的uv坐标,主要是要使得uv坐标值和纹理图像大小没有关系,比如对下面的图,uv坐标(0.5, 0.5),其实就是映射到纹理上的像素(128,128),如果换成一个更大的纹理图像(1024*1024),则(0.5,0.5)就映射到(512,512)。

    image

         对于一个三角形,我们要为每一个顶点指定uv坐标,如下图的2个三角形,我们按照图上标的纹理坐标指定uv坐标,则左边的2个三角形则会被完整的映射成右边的纹理形状。

    image

    下面了解几个和纹理采样有关的概念:

     

    Magnification与Minification:

        如果光栅化的后的三角形正好是256*256像素,这和纹理的大小正好相等,那么映射关系就是一个像素对应纹理的一个单元(texel),但实际情况可能更复杂。

     

        比如:纹理大小为256*256,但我们的两个三角形组成的quad却是512*512,则一个纹理单元要对应quad上的四个像素,一个纹理单元对应多个光栅化后的像素的情况通常称作Magnification,

     

    image

        

         在magnification情况下如何进行纹理映射呢?通常是用双线性插值的方式,比如下面左边的图中红色的pixel,没有对应的纹理texel,则它的颜色值右它的上下左右的pixel采用插值的方式得到,当然我么也可以选择最接近的纹理单元颜色做为其颜色,具体要视设置的纹理滤波中的MAG设置。

    image

         和magnification的情况相反,minification表示三角形面小,而纹理大的情况,就是一个pixel如何在多个纹理单元中选择颜色的问题。这时可以选择最接近的纹理单元,也可以把上下左右纹理单元进行双线性插值,再和pixel映射起来。比如下图128*128的quad面和256*256纹理映射的情况:

    image

    mipmap层:

          通常,我们创建纹理的时候,可以选择创建mipmp层,这时,系统就自动会为我们创建一系列下采样的图像,每个图像都是前面一个图像的1/4(如下图所示),我们可以自己选择mipmap的层数。如果使用dds文件的话,其中已经包含了mipmap层,所以最好把自己需要的纹理转化成dds格式,预处理得到需要mipmap层数。

    image

     

          在使用mipmap层的情况下,如何做纹理映射呢?

    比如纹理原始大小是256*256,我们的三角形是178*178,那么这时会做三线性插值,quad先和128*128纹理执行magnificaiton插值得到一个结果,再和256*256纹理做minification插值得到一个结果,最后再对这2个结果进行插值,得到的颜色为最终的pixel颜色。

    image

     

    纹理的寻址模式:

         通常我们顶点的纹理坐标在[0,1]范围内,这样光栅化后的三角形pixel总能从纹理中找到对应的纹理单元。

        我们也可以通过设置纹理寻址模式,来扩展纹理映射,对于不在[0,1]之间的纹理坐标,也可以找到对应的纹理单元。

     

    通常的纹理寻址模式包括:

       

    wrap方式:

         对于不在[0,1]之间的纹理坐标,采用缠绕的方式来对应纹理单元,比如下面图所示,这样的方式特别适合用小纹理来贴一个大的平面,比如在地面铺瓷砖,在地面上铺草地等等。这也要求我们设计纹理图片时,把左右、上下的边缘部分,最好能无缝的连接起来。

    image

    border方式:

        把不在[0,1]范围的纹理坐标设置为一些指定的颜色,比如下图,指定为红色

    image

    Clamp方式:

         把不在[0,1]范围的纹理坐标指定为离其最近的纹理单元颜色。

    image

    Mirror方式:

         就是把不在[0,1]范围的纹理坐标按镜像的方式指定纹理单元,如下图所示:

    image

    本章我们了解很多纹理采样的一些设置,在D3D11中使用纹理前我们必须设定采样状态,主要就是通过下面的的函数:


    // 创建纹理采样状态描述符. 
    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 
    samplerDesc.MipLODBias = 0.0f; 
    samplerDesc.MaxAnisotropy = 1; 
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 
    samplerDesc.BorderColor[0] = 0; 
    samplerDesc.BorderColor[1] = 0; 
    samplerDesc.BorderColor[2] = 0; 
    samplerDesc.BorderColor[3] = 0; 
    samplerDesc.MinLOD = 0; 
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
    
    // 创建纹理状态. 
    result = device->CreateSamplerState(&samplerDesc, &m_sampleState); 
    if(FAILED(result)) 
    { 
        return false; 
    } 
    
    
    

    本篇日志学习,我们了解D3D11纹理使用中的一些基本概念,下一篇日志,要开始写代码了…

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规