原文: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. 简单linux查询

    1查看日志异常 tailf nohup.out|grep ERROR -A 3 --color   tailf nohup.out|grep ERROR|grep chunk -A 3 -B 3 -- ...

  2. Redis源码解析:11RDB持久化

    Redis的RDB持久化的相关功能主要是在src/rdb.c中实现的.RDB文件是具有一定编码格式的数据文件,因此src/rdb.c中大部分代码都是处理数据格式的问题. 一:RDB文件格式 上图就是一 ...

  3. JavaScript的坑,缺陷

    JavaScript的缺陷 1.在做判断的时候用=======而不是== 2.浮点预算有精度问题 通过差值去把这个精度锁定到一个范围 Math. Abs(A-B)<0.0001** 3.null ...

  4. CSS min-height 属性

    实例 设置段落的最小高度: p { min-height:100px; } 浏览器支持 IE Firefox Chrome Safari Opera 所有主流浏览器都支持 min-height 属性. ...

  5. oracle之FUNCTION拙见

    一.介绍 函数(Function)为一命名的存储程序,可带参数(有无均可),有返回值 函数和过程的结构类似,但必须有一个RETURN子句,用于返回函数值. 函数说明要指定函数名.返回值的类型,以及参数 ...

  6. 系统日志和内核消息 $ dmesg$ less /var/log/messages$ less /var/log/secure$ less /var/log/auth

    查看错误和警告消息,比如看看是不是很多关于连接数过多导致? 看看是否有硬件错误或文件系统错误? 分析是否能将这些错误事件和前面发现的疑点进行时间上的比对.

  7. 洛谷P1979 [NOIP2013提高组Day2T3]华容道

    P1979 华容道 题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少 ...

  8. 【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]

    P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...

  9. Leetcode641.Design Circular Deque设计循环双端队列

    设计实现双端队列. 你的实现需要支持以下操作: MyCircularDeque(k):构造函数,双端队列的大小为k. insertFront():将一个元素添加到双端队列头部. 如果操作成功返回 tr ...

  10. Eclipse 的 Java Web 项目环境搭建

    从svn上拉取下来Eclipse的项目 IntelliJ IDEA自动识别到可编译的 src 类目录 Java Web 项目 html(一般命名为:WebRoot) 是整个项目输出的根目录. WEB- ...