凹凸/高度贴图、法线贴图、视差贴图、置换贴图异同
参考:
凹凸贴图、法线贴图、置换贴图-CSDN博客
视差贴图 - LearnOpenGL CN
1,Learn about Parallax(视差贴图) - 知乎
“视差贴图”的工作流程及原理(OpenGL) - 哔哩哔哩
法线与置换贴图原理讲解以及烘焙制作! - 知乎
1. Bump Mapping 凹凸贴图
BumpMap是一种灰度图,用表面上灰度的变化来描述目标表面的凹凸,因此这种贴图是黑白的,也可以把贴图的Alpha通道用作Bump。值得注意的是,这种贴图表面上存储的东西是高度域--即每个点和原始表面的高度差,而不是色彩,是高度,一个数值!因此,对这个贴图做任何的操作都会影响到这个物体 3d的外观质感。不能凭感觉用事。

在游戏中所使用的算法叫做fake bump mapping,假凹凸贴图。因为在游戏中BumpMap并没有改变物体的表面,而只是影响光照的结果,欺骗眼睛而已。

最简单的做法是,直接把BumpMap叠加在已经渲染好的表面上,造成亮度上的扰动,从而让人以为是凹凸的--这个很容易理解,把一面白色的墙面有技巧的部分划成灰色就会变成蚀痕,这些诸位会比小的更擅长。而计算复杂度是基本加减法。这个所谓的FakeBumpMapping 从Geforce2就开始硬件支持,但是从来没有大范围的应用过。
不过有趣的是,BumpMap这个东西却从未过时,在后来的渲染算法中,其储存表面高度域的特性仍然发挥着巨大的作用。
2. Normal Mapping 法线贴图
NormalMapping是一种凹凸贴图技术,也叫做Dot3bump mapping。
用于实现它的控制纹理是一张叫做Normal Map的纹理,这张图中存储的东西是每个原始表面法线的迭代。举例在3D模型上,表面法线就像是一根站立于桌面的钢笔,垂直向上。而NormalMap中存储的东西就是我们这支表示表面法线方向的钢笔所“应该”指向的方向--比如说朝左边倾斜15度。
NormalMap有两种主要形式,一种叫做模型空间的NormalMap,一种叫做切线空间的NormalMap。第一种在游戏中没有实用价值,我们说第二种,也就是大家最常见的一种。

模型空间下的法线纹理看起来是“五颜六色”的。这是因为所有法线所在的坐标空间是同一个坐标空间,即模型空间,而每个点存储的法线方向是各异的。
而切线空间下的法线纹理看起来几乎全部是浅蓝色的。 这是因为,每个法线方向所在的坐标空间是不一样的,即是表面每点各自的切线空间。这种法线纹理其实就是存储了每个点在各自的切线空间中的法线扰动方向。也就是说,如果一个点的法线 方向不变,那么在它的切线空间中,新的法线方向就是z轴方向,即值为(0,0, 1), 经过映射后存 储在纹理中就对应了RGB(0.5,0.5, 1)浅蓝色。而这个颜色就是法线纹理中大片的蓝色。这些蓝色 实际上说明顶点的大部分法线是和模型本身法线一样的,不需要改变。
切线空间法线优点:
- 自由度很高,模型空间下的法线纹理记录的是绝对法线信息,仅可用千创建它时的那个模型, 而应用到其他模型上效果就完全错误了。而切线空间下的法线纹理记录的是相对法线信息,把该纹理应用到一个完全不同的网格上,也可以得到一个合理的结果。
- 可进行UV动画
- 可以重用法线纹理
- 可压缩。可以仅存储 XY方向,而推导得到Z方向。
法线贴图是凸凹贴图(Bump mapping)的一种常见应用,简单说就是在不增加模型多边形数量的前提下,通过渲染暗部和亮部的不同颜色深度,来为原来的贴图和模型增加视觉细节和真实效果。简单原理是在普通的贴图的基础上,再另外提供一张对应原来贴图的,可以表示渲染浓淡的贴图。通过将这张附加的表示表面凸凹的贴图的因素于实际的原贴图进行运算后,可以得到新的细节更加丰富富有立体感的渲染效果。


关于法向贴图的更多信息,可以参考
http://en.wikipedia.org/wiki/Normal_mapping
NormalMap最大的缺点是它的视角问题。因为NormalMap只是改变的表面上的光照结果,并没有改变表面上的形状,不能实现自身内部的遮挡,因此不能表现平面上凹凸起伏比较大的场合。比如说我们一个桌面上突出一块,然后在突出的这块东西边上放一支牙签。根据经验,这个凸起会很轻易的挡住我们的视线,让我们看不见那支牙签。可是NormalMap却不会这么做,因此我们一直能看见障碍物背后的东西。
这样一来,NormalMap只能用在大家对遮挡关系不敏感的场合,比如场景等,不是不能用于人物,而是用NormalMap的人物不太经得起特写,放大了,角度刁钻了都容易穿帮。
P.S.关于NormalMap的一点秘籍。注意理解……NormalMap其实并不是从低模的表面凸出高模的细节的,而是把高模中比最高点的位置低的地方凹进去的!因此低模要比高模大一点点才会很准。大家可以想像成我们是用一个比高模稍微大一点点尺寸的低模石膏模型来把高模雕刻出来的。

3. Parallax mapping 视差贴图
视差贴图是一种Normal Mapping算法的增强算法,其本质上和Normal Mapping没有区别。优势是只需要增加3个HLSL语句和一个控制纹理通道(只需要几个GPU指令,代价小到可以忽略)就可以显著的增加物体表面的深度感。但是NormalMap中出现的问题,Parallax mapping基本上都有--特别是视角接近平行的时候,凹凸感消失的问题,并没有明显改善。或者Parallax mapping才是真正具有实用价值的Normal Mapping。
Parallax mapping使用的还是单张的控制纹理,也就是一张切线空间的NormalMap,但是Alpha通道里存储的是对应这张NormalMap的BumpMap。
视差贴图属于位移贴图(Displacement Mapping)技术的一种,它对根据储存在纹理中的几何信息对顶点进行位移或偏移。一种实现的方式是比如有1000个顶点,根据纹理中的数据对平面特定区域的顶点的高度进行位移。这样的每个纹理像素包含了高度值纹理叫做高度贴图。一张简单的砖块表面的高度贴图如下所示:

整个平面上的每个顶点都根据从高度贴图采样出来的高度值进行位移,根据材质的几何属性平坦的平面变换成凹凸不平的表面。例如一个平坦的平面利用上面的高度贴图进行置换能得到以下结果:

置换顶点有一个问题就是平面必须由很多顶点组成才能获得具有真实感的效果,否则看起来效果并不会很好。一个平坦的表面上有1000个顶点计算量太大了。我们能否不用这么多的顶点就能取得相似的效果呢?事实上,上面的表面就是用6个顶点渲染出来的(两个三角形)。上面的那个表面使用视差贴图技术渲染,位移贴图技术不需要额外的顶点数据来表达深度,它像法线贴图一样采用一种聪明的手段欺骗用户的眼睛。
视差贴图技术的主要任务是通过移动UV修改贴图来让平面看着像3D。这个效果会在片段着色器中显示的所有像素进行计算。
如下图,Level0代表没有坑洞,Level1代表最深的孔。模型实际上没有变而且一直在Level0处,曲线代表的是储存在高度图中的值。当下的像素坐落在黄色方形处,这个像素对应的UV是T0。V是从摄像机到该像素的向量。
- 如果按照T0采样高度图的话能得到值
H(T0) = 0.55,值不等于0,所以该像素并不在表面,在像素之下有坑,所以你必须延申V到由高度图定义曲面的交点T1。 - 这个交点正在深度为H(T1),然后用T1去采样diffuseMap和normalMap,得到
H(T1)=0.15。
因此所有视差算法的目标都是去计算摄像机向量V和高度图所定义表面的交点。


根据这张图可以大概知道摄像机相对片元的面上的位移越大(切线空间下的x,y轴),UV的偏移值就越大。由三角形的等比例可知
viewDir.xy / viewDir.z = texcoordOffset / height
其中height为视差贴图中采样得出的值,texcoordOffset为表面的偏移。因此
texcoordOffset = viewDir.xy / viewDir.z * height
再加一个可控的高度系数heightScale
texcoordOffset = viewDir.xy / viewDir.z * height * heightScale
现在这样的表达式可以说是比较完善了,即:
texcoord = Texcoord - texcoordOffset
(Texcoord为VAO中自带的UV值)
但是对于技术研究者来说,这样的表现显然还是不够令人满意的。因此,顺着视差贴图的思路向下发展,借助ShaderModel3.0的出现。出现了一个真正从物理上改变物体表面的算法,这就是Displacement Mapping。
4. Displacement mapping 位移贴图(置换贴图)
和前面说的几种方式不同,Displacement Mapping是一种真正改变物体表面的方式。

通过一种称为micro polygons(微多边形)tessellate(镶嵌)的技巧来实现真正的改变物体表面的细节。具体流程是这样的。
- 首先,根据屏幕的分辨率,在模型的可见面上镶嵌和最终象素尺寸相同的微多边形。这个过程叫做镶嵌。
- 然后读取一张Bump贴图。根据表面的灰度确定高度。
- 然后根据镶嵌所得到的多边形,沿着原先的表面法线方向移动微多边形。
- 接着再为新的多边形确定好新的法线方向。此时,物体的表面确实已经真的增加出了细节。
其实这种技巧,我们在使用ZBrush的时候就可以看见了。大家用过Zbrush的时候会知道,在表面刷过的细节,只有在画面静止下来之后才会越来越清晰。而微多边形镶嵌起到的就是类似的作用。只增强面对屏幕的多边形的表面粗糙细节,而不是整个模型。因此性能代价并不会像直接上高模那么大。
相比来说位移贴图在效果上是没有任何瑕疵的,但是也未必没有缺点。首先就是,对硬件的要求很高,同时镶嵌对于性能的消耗也不小。它可以用来实时生成大面积的户外地形!这是其他任何凹凸贴图方式所不能比拟的!

三种利用切空间光线追踪先进算法的技术,三种方法分别是光线跟踪,光束跟踪和圆锥跟踪算法。当然可以说后面的都是第一种的改进。这些都是面向未来的技术,很有前途。ReliefMapping甚至现在可以实现扣环这样的复杂几何表面,并且可以处理不能平视的问题!
相关文章:
凹凸/高度贴图、法线贴图、视差贴图、置换贴图异同
参考: 凹凸贴图、法线贴图、置换贴图-CSDN博客 视差贴图 - LearnOpenGL CN 1,Learn about Parallax(视差贴图) - 知乎 “视差贴图”的工作流程及原理(OpenGL) - 哔哩哔哩 法线与置换贴图原理讲解以及烘焙制作! - 知乎 1. Bump Mapping 凹凸贴图 BumpMap…...
ZSTD 内存泄漏问题
优质博文:IT-BLOG-CN Zstandard(简称zstd)是一种无损压缩算法,由Facebook开发并开源。它旨在提供高压缩比和高解压速度的平衡,适用于多种数据压缩需求。 特点 【1】高压缩比: zstd能够在保持较高压缩比的…...
c# npoi操作excel
今天在弄使用npoi对excel表的操作,遇到个问题就是使用workbook通过filestream打开后,让后workbook.write(filestream)居然报文件流关闭了,无法写入,弄了好久都不行,最后通过写2个excel文件来解决,现在看来我…...
十二:HTTP错误响应码:理解与应对
在现代网络技术中,HTTP(超文本传输协议)是浏览器与服务器之间沟通的基础。每当我们访问网站或发送请求,HTTP会返回一个响应码,这些代码不仅可以表示成功,还可以指示各种问题。本文将以HTTP错误响应码为主题,探讨其含义、常见类型及应对措施。 1. 400 Bad Request - 请求…...
Rust学习(六):函数式编程
Rust学习(六):函数式编程 我们在前一篇博客中已经介绍了如何通过trait和impl实现Rust的面向对象编程,但是Rust本身实际上并不提倡通过类来解决问题。Rust推崇的是函数式编程,强调将函数作为参数值或者其他函数的返回值…...
使用 Vue 和 Create-Vue 构建工程化前端项目
目录 前言1. 工程化的意义与 Vue 的生态支持2. 搭建 Vue 工程化项目2.1 环境准备2.2 使用 create-vue 创建项目2.2.1 初始化项目2.2.2 安装依赖2.2.3 本地运行 3. Vue 项目的目录结构解析4. Vue 开发流程详解4.1 项目入口与根组件4.1.1 main.js 的作用4.1.2 App.vue 的结构 4.2…...
opencv图片明暗度判断方法
OpenCV 的LAB 颜色空间(也称为 CIELAB)是一种颜色对手的颜色模型,它旨在模仿人类的色彩感知。LAB 颜色空间由三个分量组成: L: 亮度分量 (Lightness),范围从 0(黑色)到 100(白色&…...
QT6学习第三天
QT6学习第三天 第一个Widgets项目创建项目项目界面简单介绍编译文件介绍 我在第一天中将重点标了颜色,后边我把一些简单的东西都不写了,写了的都是实际用的东西,就不标颜色了。 第一个Widgets项目 首先我们创建一个widgets项目,…...
计算机网络-MSTP基础实验一(单域多实例)
前面我们已经大致了解了MSTP的基本概念和工作原理,但是我自己也觉得MSTP的理论很复杂不结合实验是很难搞懂的,今天来做一个配套的小实验以及一些配置命令。 一、网络拓扑 单域多实例拓扑 基本需求:SW1为VLAN10的网关,SW2为VLAN20的…...
React合成事件及其核心思想详解
相关联Javascript知识 1.JavaScript 的事件流 事件流是 JavaScript 处理事件的机制,它描述了事件从发生到被处理的过程。事件流主要包括两个阶段:捕获阶段和冒泡阶段。在捕获阶段,事件从文档的根元素开始,逐层向下传播到目标元素&…...
Datawhale模型减肥秘籍Tasking之模型量化
Datawhale模型减肥秘籍Tasking之模型量化 什么是量化?为什么量化?量化基本方法基于k-means的量化线性量化 训练后量化量化粒度动态量化参数的计算 ( Cliping )指数移动平均(EMA)Min-MaxKL 量化均方误差(MSE)…...
在云服务器搭建 Docker
操作场景 本文档介绍如何在腾讯云云服务器上搭建和使用 Docker。本文适用于熟悉 Linux 操作系统,刚开始使用腾讯云云服务器的开发者。如需了解更多关于 Docker 相关信息,请参见 Docker 官方。 说明: Windows Subsystem for Linuxÿ…...
Redis 的代理类注入失败,连不上 redis
在测试 redis 是否成功连接时,发现 bean 没有被创建成功,导致报错 根据报错提示,需要我们添加依赖: <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>&l…...
版本控制【Git Bash】【Gitee】
目录 一、什么是版本控制? 二、版本控制的种类: 1、本地版本控制 2、集中版本控制 3、分布式版本控制 三、下载Git Bash 四、Git Bash 配置 五、Git Bash使用 1、切换目录:cd 2.查看当前文件路径:pwd 3.列出当前目录下文件…...
Neo4j Desktop 和 Neo4j Community Edition 区别
Neo4j Desktop 和 Neo4j Community Edition 的主要区别在于它们的用途、功能以及安装和管理方式。以下是这两者的详细对比: 1. Neo4j Desktop Neo4j Desktop 是一个图形化的桌面应用程序,主要为开发人员和个人使用提供了一个便捷的环境来安装、管理和运…...
使用uniapp开发微信小程序使用uni_modules导致主包文件过大,无法发布的解决方法
在使用uniapp开发微信小程序时候,过多的引入uni_modules的组件库,会导致主包文件过大,导致无法上传微信小程序,主包要求大小不超过1.5MB.分包大小每个不能超过2M。 解决方法:分包。 1.对每个除了主页面navbar的页面进…...
HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)事件推荐开发者测试
意图框架向开发者提供真机测试能力,即开发者可连接设备进行调测。开发者完成代码开发之后,功能正式上架应用市场前,可以在HarmonyOS NEXT设备上面进行自验证,打磨体验。真机测试分为三个步骤:基础信息提供,…...
GD32F103 实践-- MCU编译运行
编译 打开固件库示例工程:在SDK路径下找到固件库示例工程,路径通常是SDK\GD32F10x_Firmware_Library_Template\Keil5_project\Project 选择芯片型号:根据你的MCU型号选择,例如GD32F103RCT6 修改宏定义:根据MCU型号修…...
SQL复杂数据类型处理
背景 数据处理中,经常碰到复杂数据类型,需要将他们进行解析才能利用。 复杂数据类型 1、MAP结构转为列 WITH tmp AS ( SELECT {"Users":{"4418":{"UserId":4418,"Score":0,"IsStudent":true},&q…...
ROS第九梯:ROS+VSCode+Python+C++自定义消息发布和订阅
首先,Python版本的ROS项目和C++版本的ROS项目前期创建功能包的步骤基本一致,具体可参考第二章。 费一步:新建msg文件 在功能包(data_input)目录下创建一个msg文件夹,并在msg文件夹下创建一个名为Box的msg文件,具体如下图所示: 该msg文件为一个用于描述3D Box的文件,…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
