3D编程:第九章 Normal Mapping and Displacement Mapping

第九章 Normal Mapping and Displacement Mapping

本章主要讲述两种图形学技术,支持在不增加objects的poly primitive的情况下,在场景中增加更多的细节。第一种是normal mapping,通过创建一些“fake” geometry(虚设的多边形图元)模拟光照作用。第二种是displacement mapping,根据纹理数据moving vertices actually(与“fake”相对应,这里指真实的移动)来创建凹凸不平的表面。

Normal Mapping(法线贴图)

前面几章,已经讨论了specualr maps,environment maps以及transparency maps,这些texture maps都提供了附加的数据信息。Specular maps中的数据用于限制specular highlight,environment maps则包含了用于reflective surfaces的colors,transparency maps用于控制output-merge阶段的alpha blending。这些额外的信息由每一个pixel提供,比仅由每一个vertex提供,具有更高的精度。同样 ,一个normal map也是对每一个pixel都提供表面的法向量数量,该额外的数据可以应用于多种技术上。

Normal maps的其中一个应用是虚构一个凹凸表面的细节,比如石墙。可以使用足够的geometry来模拟这中凹凸不平的墙面,使用的vertices越多,得到的细节也越多。这样就可以在场景中更好的处理光照,远离光源的石块就会显示为较暗的区域。但是,增加geometry会导致计算成本也增大。相反,对于一个含有少量poly geometry的object(即使是一个flat plane),使用normal map方法,也可以模拟与大量增加geometry情况下同样的光照效果。这种应用就称为normal mapping。

Normal Maps

图9.1中显示了用于一面石墙的color map(左图)和normal map(右图)。相对于color map,normal map看起来有点奇怪。虽然可以把norml map显示出来,但是normal map中存储的是3D directions vectors(3维的方向向量)。对normal map进行采样时,从RGB通道中得到的结果表示方向向量的x,y,z分量。这些法向量可用于一些效果的计算,比如diffuse lighting。

图9.1 A color map (left) and normal map (right) for a stone wall. (Textures by Nick

Zuccarello, Florida Interactive Entertainment Academy.)

RGB texture的每一个channels都存储一个unsigned 8-bit值(unsigned char),该类型的数值范围为[0, 255]。但是一个规范化的方向向量,对应的xyz各个分量值范围是[-1, 1]。因此,法线向量存储到texture之前必须先转换到范围[0, 255],对texture进行采样的时候必须再转换到范围[-1, 1]。可以使用如下的公式,把浮点型向量从范围[-1, 1]转换到范围[0, 255]:

f(x) = (0.5x + 0.5) * 255 再使用下面的方程式变换回来:

实际工作中,一般会使用图像处理软件(比如Adobe Photoshop)把一个normal map编码成RGB texture格式。但是采样texture时需要在shader中手动计算,把数据从范围[0, 255]转换回[-1, 1]。在采样过程中已经执行了浮点除法(除以255)操作,所以得到的采样结果在范围[0, 1]之间。因此,只需要使用下面的方程函数把范围[0, 1]转换到范围[1, 1]:

f(x) = 2x 1 或者,也可以使用16位或32位浮点型数值作为normal maps的texture格式,这样可以产生更好的细节效果,但会牺牲一些性能。

Tangent Space(切空间)

一般使用每一个vertex的法线来计算diffuse,同样也可以使用每一个pixel的法线。但是法线必须与light处于同一个坐标空间。对于per-vertex法线,由object space提供。但是normal maps的法线值处于tangent space。

Tangent space(或者texture space)是一个相对于纹理的坐标系,由三个相互正交的向量确定:surface normal向量,tangent向量以及binormal向量。图9.2描述了这三个向量。

图9.2 An illustration of tangent space. (Texture by Nick Zuccarello, Florida Interactive Entertainment Academy.)

其中normal向量,N,是一个vertex的表面法向量。Tangent向量,T,与表面的法线垂直,与指向texture的u轴方向。Binormal向量,B,则指向texture的v轴方向。

可以使用这三个向量创建一个TBN(tangent, binormal, normal)变换矩阵,如下所示:

可以使用这个矩阵把向量由tangent space变换到object space中。但是,由于light vector通常是在world space中,因此需要把从normal map中采样得到的noraml从tangent space变换到world space。或者换一种方式,直接使用已经处于world space中的向量创建TBN矩阵。

时间: 2024-10-30 05:57:39

3D编程:第九章 Normal Mapping and Displacement Mapping的相关文章

《.net编程先锋C#》第九章 配置和调度(转)

编程 第九章 配置和调度在上一章,你学到如何创建一个通用语言运行时(CLR)组件,且如何在一个简单的测试应用程序中使用它.虽然CLR组件就要准备装载了,但你还是应该思考以下技术之一:.条件编译.文档注释.代码版本化 9.1 条件编译 没有代码的条件编译功能,我就不能继续工作.条件编译允许执行或包括基于某些条件的代码:例如,生成应用程序的一个查错(DEBUG)版本.演示(DEMO)版本或零售(RELEASE)版本.可能被包括或被执行的代码的例子为许可证代码. 屏幕保护或你出示的任何程序.在C#中,

3D编程:Displacement Mapping(移位贴图)

Displacement Mapping(移位贴图) Normal maps的另一个应用是displacement mapping,在这个应用中,细节的增加不再是通过虚拟光照得到的,而是真正的改变模型的vertices.使用displacement mapping时,vertex沿着它的法线向量平移,该法线的值由一个displacement map指定.一个displacement map就是一个高度纹理图,只有一个通道值,并且存储了高度的大小.图9.4就是本章一直使用的stone wall t

3D编程:Environment Mapping

Environment Mapping Texture cubes的另一种应用是environment mapping.Environment mapping也称为reflection mapping,用于近似模拟reflective surfaces(反光表面),比如汽车上的镀了一层金属物的保险杠. Environment mapping的处理过程比skybox稍微复杂一些,因为需要计算光线与表面的反射向量.反射向量主要由view direction(限入射角向量)和表面的法向量计算得到.具体

新手求教 谢谢-c primer plus 编程练习第九章

问题描述 c primer plus 编程练习第九章 设计函数chline(ch, i, j),实现指定字符在i列到j列的输出,并用一个简单的驱动程序测试该函数. #include<stdio.h> void chline(char ch , int i , int j); int main(void) { int i = 0; int j = 0 ; char ch = ' '; printf("enter the char you want to print:"); c

《OpenGL超级宝典(第5版)》——第1章,第1.4节3D编程的基本原则

1.4 3D编程的基本原则 现在,我们对实时3D的基本概念已经有了相当程度的认识.我们讨论了一些术语以及PC上的一些示例应用程序.那么,如何在自己的计算机上创建这样的图像呢?好吧,这正是本书剩余部分的任务所在.不过,读者还需要知道一些基础知识,这正是我们接下来将要讨论的. 1.4.1 并非工具包 OpenGL基本上是一种底层渲染API(应用程序接口).我们不能告诉它"在什么地方绘制什么"--我们需要自己动手,通过载入三角形,应用必要的变换和正确的纹理.着色器并在必要时应用混合模式来组合

c++-我现在该学什么?window程序设计啃到第九章,想学MFC但是已经过时了,C++的路下面该怎么走

问题描述 我现在该学什么?window程序设计啃到第九章,想学MFC但是已经过时了,C++的路下面该怎么走 我是自修计算机,连本科文凭都是家里蹲自考的,主修C++,现在不知道该学什么了,<window程序设计>只啃到第九章,啃不下去了,太多的API函数,在啃下去也是浪费时间,最多就是熟悉些API的运用....然后啃<深入浅出MFC>今天啃到第三篇有卡住了,也不想在MFC上浪费太多时间.....我下面该学什么.....完全没有方向呀,C++的路下面该怎么走...... 解决方案 AP

第九章 方法[《.net框架程序设计》读书笔记]

.net框架|笔记|程序|设计 第九章 方法 一. 实例构造器 1. 前面提到用new操作符创建对象时的三部曲: l 为对象分配内存 l 初始化对象的附加成员(方法表指针和SyncBlockIndex) l 调用实例构造器初始化实例状态 在分配内存时,系统将所有内存位置均置为0值,这就是为什么字段初始化而未赋值时均为0或null值. 不调用实例构造器的情况: l 调用Object.MemberwiseClone()方法创建实例(分配内存:初始化附加成员:将源对象字节拷贝到新创建的对象) l 反序

J2ME 3D编程——第一个3D程序

编程|程序 J2ME 3D编程--第一个3D程序(附源代码) 更多文章请访问:http://blog.csdn.net/mailbomb 参考WTK2.2提供的demo,完成了第一个3D程序,虽然很简单,而且有些问题还不是很清楚,还是把代码共享出来和愿意学习J2ME 3D编程的朋友一起学习. 关于3D编程的资料,可以查阅我的blog. 关于代码的编译和运行说明如下: 1. 以下代码在J2ME WTK2.2下面编译通过. 2. 代码分为两个文件:First3DCanvas.java和First3D

J2ME 3D编程——第一个3D程序(附源代码)

参考WTK2.2提供的demo,完成了第一个3D程序,虽然很简单,而且有些问题还不是很清楚,还是把代码共享出来和愿意学习J2ME 3D编程的朋友一起学习. 关于3D编程的资料,可以查阅我的blog. 关于代码的编译和运行说明如下: 1.以下代码在J2ME WTK2.2下面编译通过. 2.代码分为两个文件:First3DCanvas.java和First3DMIDlet.java. 3.使用J2ME WTK2.2建立新的工程,主MIDlet类为:first3d. First3DMIDlet 4.将