本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/5018103.html


凹凸贴图 Bump Mapping

一、简介

凹凸贴图用于在不增加模型的几何复杂度的情况下模拟几何体表面的复杂细节,从而增加真实感。通过将影响物体光照外观的表面特征存入纹理中,使用凹凸贴图的优点有:

  • 在不增加更多几何体的情况下提供更高的视觉复杂度。

  • 简化模型的制作。

  • 为同一个模型提供不同的表面外观。

二、砖墙法线贴图 The Brick Wall Normal Map

1. 意义

在真实世界中,砖墙是由砂浆和砖块堆砌成的,形成的表面并不平坦。在虚拟世界中构建砖墙时,可以通过为砖墙的每一个凹凸细节都构建多边形并设置表面法线来展现这些细节,但这种方法需要的多边形数目可能是一个天文数字。因此,通常做法是采用法线贴图的方式模拟这些细节。

2. 将凹凸贴图存储为法线贴图

1) 法线贴图

凹凸贴图具有多种不同的形式,接下来会介绍使用表面法线代表物体表面变化的凹凸贴图,这种类型的凹凸贴图通常被称为法线贴图。

2) 法线贴图的存储形式

法线贴图中存储的法线通常为三元单位向量,由于纹理贴图中,色彩的取值范围会被限制在[0.0f, 1.0f]之间,而法线向量的取值范围在[-1.0f, 1.0f]之间,所以通常会采用下面的公式进行转换:

ColorComponent = 0.5 * NormalComponent + 0.5

NormalComponent = 2 * (ColorComponent - 0.5)

注:现代GPU已经支持有符号纹理贴图,是否采用这种转换取决于项目需要。

3) 通过高度场生成法线贴图 Generating Normal Maps from Height Fields

高度场纹理使用单个字节存储了每一个纹理像素(texel)的高度。将高度场转化为法线贴图的步骤如下:

A. 取目标像素点高度Hg,目标相邻右侧像素点高度Hr,目标相邻上侧像素点高度Ha

B. 计算目标像素点至右侧像素点的方向向量(1, 0, Hr - Hg)和目标像素点至上侧像素点的方向向量(0, 1, Ha - Hg)

C. 计算上一步中两个方向向量的叉积,并标准化。公式如下:

Normal = (Hg - Ha, Hg - Hr, 1) / sqrt((Hg - Ha)2 + (Hg - Hr)2 + 1)

D. 对获取的法线单位向量进行压缩处理(将各分量取值范围从[-1.0f, 1.0f]压缩至[0.0f, 1.0f]之间)

由于砖墙的大体为一个平面,因此它的大多数法线单位向量为(0, 0, 1),所以它的法线贴图主要呈蓝色。

  • 构建标准化立方贴图

一般情况下,向量标准化的计算公式为:

NormalizeV = V / sqrt(dot(V, V))

而在NVidia的CG着色器语言标准库中,包含了一个名为标准化单位向量的规范例程,它通过将预先计算好的标准化结果存储在立方贴图中的方式获取向量的标准化结果。而这种方式比使用公式进行计算要快得多。

3. 对复杂几何体使用凹凸贴图

1) 凹凸贴图的局限性

在上面的例子中,描述了凹凸贴图在一个简单的例子中如何使用:砖墙的表面是平坦、均匀且 正常的,纹理坐标与分配到的顶点位置是一个简单统一的线性映射。然而,在实际情况中,任意几何体的纹理坐标(s, t)与对象空间的位置坐标(x, y)往往不是简单的线性关系,物体表面法线的单位向量多数情况下也不是(0, 0, 1),这种情况下直接对应会产生错误的结果。

2) 对象空间凹凸贴图

为了纠正上述错误,一种解决方案就是使法线贴图的中存储的法线方向与对象空间保持一致。

【优点】不需要额外的计算

【缺点】法线贴图不能在不同模型之间共用

对有动画的模型来说,每个动作都需要独立的法线贴图

3) 纹理空间凹凸贴图

将光线向量和半角向量转换到纹理空间,从而计算光照。

【优点】可以多个对象或在对象动画中共享法线贴图

【缺点】需要对每个顶点执行两次额外的向量变换

三、砖块地板法线贴图 The Brick Floor Normal Map

砖块地板在砖墙的基础上发生了旋转,表面法线由(0, 0, 1)变为了(0, 1, 0)。为了与砖墙共用同一张法线贴图,我们需要使用旋转矩阵对光线的方向向量进行旋转。

表示三维向量旋转的变换矩阵具有如下性质:

  • 每行 / 每列都是一个单位向量
  • 每列向量都与其他两列向量正交

我们分别称旋转矩阵的三个列向量为切线Tangent、副法线Binormal与法线Normal。

知道其中任意两列向量,便可根据正交性质求得第三列。

因此在着色器中,我们只需要为每个顶点定义切线和法线属性,就可以通过叉积公式求得顶点的纹理空间转换矩阵。

四、环面体法线贴图 Bump Mapping a Torus

1. 环面体的数学表达

对环面体使用凹凸贴图比在上一章节中描述的情况更加复杂,但又比对任意多边形使用凹凸贴图简单许多。

下面是环面体的顶点坐标的参数方程(以坐标轴原点为中心,放置于xOy平面):

x = (M + N · cos(2πt) · cos(2πs)

y = (M + N · cos(2πt) · cos(2πs)

z = N · sin(2πt)

  • M为圆环中心到管道圆心的半径
  • N为管道的半径
  • (s, t)∈[0, 1],s表示了顶点在圆环上的相对位置,t表示了顶点在管道上的相对位置

2. 计算光向量转换至环面体纹理空间的旋转矩阵

创建旋转矩阵需要用到环面体参数方程的偏导数:

我们把“包含s或t的偏导数”组成的三维向量称为逆梯度,因为它类似于每个分量的常规地图的倒数。一个逆梯度表示了一个单参数变量在物体表面位置的瞬时方向与变化幅度。

我们可以用逆梯度来构建一个表面局部坐标系Surface-Local Coordinate System,创建一个3D坐标系需要两个正交的向量。对表面局部坐标系来说,表面法线向量非常关键,我们可以通过计算两个不重合的逆梯度来获取法线向量N。

再选择其中一个逆梯度作为切线,就可以构建一个表面局部坐标系了。

综上所述,环面体的旋转矩阵为:

      

其中,向量上方的∧符号表示标准化向量。

五、纹理多边形网格凹凸贴图 Bump Mapping Textured Polygonal Meshes

1. 研究单个三角形 Examining a Single Triangle

上图是一个外星人头部的线框模型,它展示了同一个三角形三次:

  • 最左边:处于2D高度场纹理中
  • 最右边:处于3D对象空间中
  • 最中间:处于使用凹凸贴图渲染的图像结果中

其中,三角形的每个顶点都对应了一个三维对象空间坐标与二维纹理坐标,它们共同组成了一个五维坐标,因此,我们可以把一个三角形描述如下:

V0 = (x0, y0, z0, s0, t0)

V1 = (x1, y1, z1, s1, t1)

V2 = (x2, y2, z2, s2, t2)

由于这些坐标处于同一个三角形所在的平面,所以可以用推导出x、y、z分别与s、t有关的平面方程:

A0x + B0s + C0t + D0 = 0

A1x + B1s + C1t + D1 = 0

A2x + B2s + C2t + D2 = 0

对上面每个等式来说,你都能通过三角形的三个五维顶点坐标计算出A、B、C、D的值。以第一个等式为例:

重写平面方程,即可得到使用s、t表示x、y、z的等式:

x = (-B0s - C0t - D0) / A0

y = (-B1s - C1t - D1) / A1

z = (-B2s - C2t - D2) / A2

上述方程为我们提供了使用纹理坐标获取对应三维对象空间坐标的途径,与环面体类似,我们可以通过逆梯度求得旋转矩阵:

注:如果模型提供了顶点法线,则优先使用模型提供的顶点法线。

2. 注意事项

1) 纹理空间与对象空间的正交性

使用上述公式计算逆梯度时,需要保证s与t的逆梯度是正交的。实际项目中,美术往往会使s与t的逆梯度正交,以避免纹理贴图倾斜。

2) 警惕纹理空间中面积为零的三角形

若三角形在纹理空间中面积为零或近似为零(可能在对象空间中仍有面积),将会逆梯度无法正确求值,从而产生不正确的光照效果,因此在使用凹凸贴图时,美术需要避免创建这样的三角形。

3) 纹理空间中的负面积三角形

由于很多模型是对称的,美术可以只绘制一半纹理,将纹理同时通过正向和反向映射到对称的网格中,这种方式应当在凹凸贴图中避免出现,否则会导致凹凸贴图在反向映射的部分效果不正确。

4) 凹凸贴图的纹理坐标非均匀拉伸

不均匀的拉伸可能会导致高度场转化而成的法线贴图不正确。

《The Cg Tutorial》阅读笔记——凹凸贴图 Bump Mapping的更多相关文章

  1. 《The Cg Tutorial》阅读笔记——环境贴图 Environment Mapping

    本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/p/4969956.html 环境贴图 Environment Mapping 一.简介 环 ...

  2. exploit writing tutorial 阅读笔记总结

    近日阅读Corelan Team编写的exploit writing tutorial系列,大致了解了一下原理,记了一些笔记.此系列文章有中文翻译版,在看雪论坛上发表. 英文版地址:https://w ...

  3. "Becoming Functional" 阅读笔记+思维导图

    <Becoming Functional>是O'Reilly公司今年(2014)7月发布的一本薄薄的小册子,151页,介绍了函数式编程的基本概念.全书使用代码范例都是基于JVM的编程语言, ...

  4. 3DShader之法线贴图(normal mapping)

    凹凸贴图(bump mapping)实现的技术有几种,normal mapping属于其中的一种,这里实现在物体的坐标系空间中实现的,国际惯例,上图先: 好了讲下原理 可以根据高度图生成法线量图,生成 ...

  5. Shader中贴图知识汇总: 漫反射贴图、凹凸贴图、高光贴图、 AO贴图、环境贴图、 光照纹理及细节贴图

    原文过于冗余,精读后做了部分简化与测试实践,原文地址:http://www.j2megame.com/html/xwzx/ty/2571.html   http://www.cnblogs.com/z ...

  6. 《The Cg Tutorial》阅读笔记——动画 Animation

    这段时间阅读了英文版的NVidia官方的<The Cg Tutorial>,借此来学习基本的图形学知识和着色器编程. 在此做一个阅读笔记. 本文为大便一箩筐的原创内容,转载请注明出处,谢谢 ...

  7. Hadoop阅读笔记(四)——一幅图看透MapReduce机制

    时至今日,已然看到第十章,似乎越是焦躁什么时候能翻完这本圣经的时候也让自己变得更加浮躁,想想后面还有一半的行程没走,我觉得这样“有口无心”的学习方式是不奏效的,或者是收效甚微的.如果有幸能有大牛路过, ...

  8. <<Java并发编程的艺术>>-阅读笔记和思维导图

    最近在坚持每天阅读<>,不但做好笔记(MarkDown格式),还做好思维导图. 如果大家感兴趣,可以可以到码云上阅读笔记和到ProcessOn上阅读思维导图. 码云:https://git ...

  9. 阅读笔记 1 火球 UML大战需求分析

    伴随着七天国庆的结束,紧张的学习生活也开始了,首先声明,阅读笔记随着我不断地阅读进度会慢慢更新,而不是一次性的写完,所以会重复的编辑.对于我选的这本   <火球 UML大战需求分析>,首先 ...

随机推荐

  1. arya使用流程

    1.github中的项目clone到本地(路径在最后),然后将arya文件夹复制到你的django工程中作为一个独立的app,该app实现了RBAC(基于角色的权限访问控制Role-Based Acc ...

  2. java知识框架

    从网上摘录的一张很经典的java学习框架图,和大家分享一下.

  3. link cut tree模板(LCT模板)

    update:2017.09.26 #include <bits/stdc++.h> using namespace std; struct Link_Cut_Tree { + ; ], ...

  4. The 15th UESTC Programming Contest Preliminary J - Jermutat1on cdoj1567

    地址:http://acm.uestc.edu.cn/#/problem/show/1567 题目: Jermutat1on Time Limit: 3000/1000MS (Java/Others) ...

  5. 虚拟机Linux系统忘记密码的情况下,修改root或其他用户密码

    使用场景 linux管理员忘记root密码,需要进行找回操作. 注意事项:本文基于centos7环境进行操作,由于centos的版本是有差异的,继续之前请确定好版本. 步骤 一.重启系统,在开机过程中 ...

  6. java的接口为什么不能实例化

    java的接口为什么不能实例化呢?首先,我们需要明白实例化的含义.实例化实际意义是在jvm的堆中开辟出一块内存空间,比如Student s = new Student();此处声明Student对象s ...

  7. Python 实例2—购物车

    老男孩教学学习笔记 """启动程序后,让用户输入工资,然后打印商品列表允许用户根据商品编号购买商品用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒可随机退出,退出 ...

  8. hashmap总结2

    1.  关于HashMap的一些说法: a)  HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体.HashMap的底层结构是一个数组,数组中的每一项是一条链表. b)  Hash ...

  9. Ubuntu 下安装Beyond Compare【转】

    本文转载自:https://blog.csdn.net/bingyu9875/article/details/52856675 官网下载安装包:http://www.scootersoftware.c ...

  10. [BZOJ5102]Prawnicy

    Description 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大. Input 第一行包含两个正整数n,k(1<= ...