原文:Directx11教程(31) 纹理映射(1)

        在前面的例子中,我们要么是直接给顶点赋颜色值,要么是在顶点属性中设置Diffuse和Specular系数,从而根据光照参数计算得到物体表面颜色,但这样得到的颜色真实感要差很多。如果我们直接把一副图像映射到三角形面上,从而得到物体表面颜色值,效果会好很多,比如下面的两幅图,右边的图是把一副图片映射到2个三角形上。

 

      甚至,我们还可以直接使用图像的颜色值做为顶点(或者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)。

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

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

Magnification与Minification:

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

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

    

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

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

mipmap层:

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

 

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

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

纹理的寻址模式:

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

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

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

wrap方式:

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

border方式:

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

Clamp方式:

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

Mirror方式:

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

现在我们了解一些纹理采样的设置,在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纹理使用中的一些基本概念,下一篇日志,要开始写代码了…

Directx11教程(31) 纹理映射(1)的更多相关文章

  1. Directx11教程(43) 纹理映射(13)-动态纹理映射

    原文:Directx11教程(43) 纹理映射(13)-动态纹理映射      本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变水面的纹理坐标,实现水面纹理 ...

  2. Directx11教程(42) 纹理映射(12)-简单的bump mapping

    原文:Directx11教程(42) 纹理映射(12)-简单的bump mapping        有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候 ...

  3. Directx11教程41 纹理映射(11)

    原文:Directx11教程41 纹理映射(11)     1.第一副图我们采用各性异性的滤波方式,并设置最大各性异性值为8.     samplerDesc.Filter =  D3D11_FILT ...

  4. Directx11教程40 纹理映射(10)

    原文:Directx11教程40 纹理映射(10)      本章尝试使用纹理行列式,或者说纹理数组,在ps中,使用2个纹理,最终的像素颜色,是光照颜色*纹理1采样颜色*纹理2采样颜色,主要是想达到如 ...

  5. Directx11教程39 纹理映射(9)

    原文:Directx11教程39 纹理映射(9)     在myTutorialD3D11_32中,我们在PlaneModelClass中增加一个纹理TextureClass* m_Texture;读 ...

  6. Directx11教程38 纹理映射(8)

    原文:Directx11教程38 纹理映射(8)      上篇日志中,我们用纹理和光照颜色调制的方式得到最终颜色,本章我们尝试用纹理采样的颜色,直接做为材质的漫反射系数Kd,并用它来做光照计算,最后 ...

  7. Directx11教程37 纹理映射(7)

    原文:Directx11教程37 纹理映射(7)     本章是在教程35.36的基础上来实现一个光照纹理结合的程序,就是把场景中旋转的cube加上纹理.    lighttex.vs中顶点的结构现在 ...

  8. Directx11教程36 纹理映射(6)

    原文:Directx11教程36 纹理映射(6)    本章主要是整理代码,做以下两件事情: 1.把世界坐标矩阵的计算,放在GraphicsClass的渲染函数中,之前放在D3DClass中,而且只是 ...

  9. Directx11教程(35) 纹理映射(5)

    原文:Directx11教程(35) 纹理映射(5)     到现在为止,我们的TextureClass初始化函数非常简单,说白了就是一行代码: result = D3DX11CreateShader ...

随机推荐

  1. MyBatis配置文件(七)--environments运行环境

    一.environments配置信息: environments的作用是用来配置数据库信息,可以配置多个,其有两个可配的子元素,分别是:事务管理器transactionManager和数据源dataS ...

  2. PAT甲级——A1055 The World's Richest

    Forbes magazine publishes every year its list of billionaires based on the annual ranking of the wor ...

  3. Leetcode98. Validate Binary Search Tree验证二叉搜索树

    给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右子树自身必须也是二叉搜索 ...

  4. Redis源码解析:22sentinel(三)客观下线以及故障转移之选举领导节点

    八:判断实例是否客观下线 当前哨兵一旦监测到某个主节点实例主观下线之后,就会向其他哨兵发送"is-master-down-by-addr"命令,询问其他哨兵是否也认为该主节点主观下 ...

  5. Django项目:CRM(客户关系管理系统)--35--27PerfectCRM实现King_admin编辑复选框

    #admin.py # ————————01PerfectCRM基本配置ADMIN———————— from django.contrib import admin # Register your m ...

  6. CSS中position和header和overflow和background

    <!DOCTYPE html> <!--CSS中position属性--> <html lang="en"> <head> < ...

  7. 斐波那契字符串_KMP

    前言:通过这道题恶补了一下字符串匹配的知识 思路:首先就是求出菲波那切字符串,这个很简单,但是要注意递归超时的问题,可以考虑加上备忘录,或者用递推法,接下来就是匹配问题了,常规的BF会超时,所以要用K ...

  8. socket.io的基本使用

    服务端: 1.监听客户端连接: io.on("connection",socket=>{ }); 不分组数据传输:传输对象为当前socket 2.1给该socket所有客户端 ...

  9. VSCode 配置阿里云CentOS 7.6 远程开发

    配置步骤 一.windows 10 开发机配置 windows 10 1809后支持ssh命令 1.生成ssh密钥.使用以下命令,先生成本地公钥和私钥ssh-keygen -t rsa -b 4096 ...

  10. JavaScript 面试:什么是纯函数?

    原文:Eric Elliott  译文:众成翻译 www.zcfy.cc/article/master-the-javascript-interview-what-is-a-pure-function ...