法线贴图与位移贴图

2024-05-24 18:18
文章标签 位移 贴图 法线

本文主要是介绍法线贴图与位移贴图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

法线贴图是一副纹理图,只是纹理图上的点保存的不是RGB数据,我们是将压缩过的x,y,z轴坐标保存到red,greed,blue分量中,这个xyz坐标定义了一个法线方向

因此法线贴图的每个像素都保存了一个法线向量。下图显示了一个形象的normal map例子:



保存在法线贴图中的法线是相对于由向量T(x轴),B(y轴),N(z轴)定义的纹理空间坐标系的

T向量在纹理图像中是水平向右的,B向量在纹理图像中是竖直向下的,N向量是和纹理平面正交的


Note:正如上图中显示的,这些向量通常是z轴对齐的(上图中N是z轴),因此z轴坐标占有最大的量,

所以,当将法线贴图作为颜色图像来浏览时,通常显示为蓝色。这是因为z轴坐标是保存在蓝色通道而且有最大的量,颜色上占有主导地位


那么我们该怎么将一个单位向量压缩为这种格式呢?首先注意的是对于一个单位向量而言,每个分量坐标总是位于[-1,1]的范围内

假如我们将这个范围偏移并缩放为[0,1]并且乘以255并截断为十进制,那么结果将会变为[0,255]范围内的一个整数,就是说,

假如x是一个在[-1,1]范围内的坐标值,那么整数部分f(x)是一个在范围0-255内的整数,函数定义为:

因此保存一个单位向量在一个24位图像中,我们仅对每个坐标应用函数f(x),并且将得到的值写到纹理图的相应颜色通道中

下一个问题是如何恢复压缩操作,也就是说,给定一个范围在0-255的压缩过的纹理坐标,怎样才能恢复在[-1,1]范围内的真值

方法是简单的应用函数f(x)的逆,稍微思考一下,我们能得到这个公式:

那就是说,假如x是一个属于0-255范围内的整数,那么是一个在[-1,1]范围内的浮点数


我们不需要自己做压缩操作,我们可以使用PhotoShop插件将图像转换为法线贴图,

然而,当我们在像素着色器中对法线贴图进行采样时,我们将不得不做恢复操作的部分以将其解压缩。

当我们在着色器中像下面这样采样法线贴图:

float3 normalT = gNormalMap.Sample(gTriLinearSam , pin.Tex);

颜色向量normalT将得到规格化的分量(r , g , b), 0 ≤ r, g, b ≤ 1

因此这个方法已经为我们做了一部分解压操作(即除以255,用于将一个0-255范围内的数转换到浮点数区间[0 ,1])

我们通过偏移,缩放将每个分量从[0 , 1]转换到[-1 , 1]完成操作,使用函数g : [0 , 1]   [-1 , 1] , 定义如下:

在代码中,我们像这样对每个颜色分量应用这个函数:

//Uncompress each component from [0 , 1] to [-1 , 1]
normalT = 2.0f * normalT - 1.0f;

这个标量1.0被解释为向量(1 , 1 , 1),使得表达式有意义并且可以逐分量运算



考虑一个3D纹理映射三角形,为了便于讨论,假设纹理映射没有失真,换句话说,映射纹理三角形到3D三角形需要进行一个

刚体变换(平移和缩放),现在,假设纹理像一幅贴花纸,因为我要拿起贴花纸,然后移动它,旋转它,使其与3D三角形重合。

图2显示了3D三角形的纹理空间坐标系:它们与三角形相切,且位于三角形平面。当然,三角形的纹理坐标时相对于纹理空间坐标系。

结合三角形面法线N,我们在三角形平面获得一个基于TBN的三维坐标系,我们将其叫做纹理空间或者切线空间。

注意切线空间通常是从一个三角形变换到另一个三角形(见图三)


图2:三角形的纹理空间和对象空间的关系。3D切线向量T与纹理坐标系的u轴对应,3D切线向量B与纹理坐标系的v轴对应


图3:盒子的每个面的纹理空间是不同的


正如图1所示,在法线贴图中的法线向量是定义在纹理空间(即切线空间)的, 但是我们的光线是定义在世界坐标系空间。

为了进行光照计算,法线向量和光线需要在同一空间。因此我们要做的第一步是找到切线空间坐标系与对象空间坐标系(物体的局部坐标系)

的关联。一旦我们是在对象空间(局部坐标系),我们能够使用世界矩阵将其从局部空间转换到世界空间。用v0 , v1 , v2表示对应的纹理坐标为

(u0 , v0) , (u1 , v1) , (u2 , v2) 的三个顶点,这三个顶点定义了一个相对于纹理空间轴(如,T和B)的纹理平面。让 , 

作为3D三角形的两条边向量,其对应的纹理坐标为和 

看图2,能够清楚的得出:

用相对于局部空间的坐标表示向量,我们能得到以下这个矩阵等式:

注意:我们知道三角形顶点的局部空间坐标,因此我们知道边向量的局部空间坐标,因此矩阵:

是已知的,同样的,我们也知道顶点的纹理坐标,因此矩阵:

也是已知的,为了解出T,B的局部空间坐标,我们得到以下的式子:

在上面,我们使用了定理,矩阵的逆为:

注意:向量T,B在局部空间中通常不是单位长度,假如纹理失真,他们将不再正交

向量T,B和N通常分别被简称为切线,副法线(副切线),和法线向量




我们已经推导了每个三角形的切线空间,然而,假如我们为法线贴图使用这个纹理空间(切线空间),我们将得到一个三角形的外观

因为这个三角形的切线空间是恒定的。因此,我们为每个顶点指定其切线空间,我们做了与顶点法线逼近平滑曲面同样的取平均值技巧:

1:面元的任意顶点的切线向量T由面元中所有共享该顶点的三角形的切线向量取平均值得到

2:面元的任意顶点的副切线向量B由面元中所有共享该顶点的三角形的副切线向量取平均值计算得到


通常来说,取均值后,基于TBN的坐标系将会正交,因此TBN向量是相互正交的且为单位长度。

这通常由施密特程序来完成。为任意三角形面元的每一个顶点生成切线坐标的代码在网页:点击打开链接中是可用的


在我们的系统中,我们将不直接将副法线向量B保存在内存中,相应的,当我们需要B向量时,我们可以计算B = N x T

N是平均顶点法线,因此,我们的顶点结构体应该是这样的:

namespace Vertex
{struct NormalMap{XMFLOAT3 Pos;XMFLOAT3 Normal;XMFLOAT2 Tex;XMFLOAT3 TangentU;};
}
在程序中,由GeometryGenerator创建生成的面元计算纹理空间(切线空间)中与u轴对于的切线向量T。

正方体和网格中每个顶点的切线向量T的局部空间坐标都是非常容易指定的,对于圆柱和球体,每个顶点的切线向量T

可以通过由两个变量组成的矢量值函数计算偏导数得到

参数u是纹理坐标u




此时,我们能够得到面元中每个顶点的TBN正交坐标系(切线坐标系)。而且,我们有TBN向量在面元局部空间中的坐标。

现在我们有基于TBN向量为坐标轴(切线空间)的点的坐标,我们能够将坐标从切线空间转换到局部空间,使用这个矩阵:


的关联,,das

这篇关于法线贴图与位移贴图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/999161

相关文章

Open3D 基于法线的双边滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数: 输出参数: 参数影响: 2.2完整代码 三、实现效果 3.1原始点云 3.2滤波后点云 Open3D点云算法汇总及实战案例汇总的目录地址: Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客 一、概述         基于法线的双边

图形API学习工程(25):实现法线贴图

工程GIT地址:https://gitee.com/yaksue/yaksue-graphics 目标 在《图形API学习工程(10):基础光照》中,我实现了最基础的光照,同时也表现了法线的作用。 在《图形API学习工程(11):使用纹理》中,工程已经能够加载纹理贴图。 这样,法线贴图 所需的准备已经完成,可以在工程里实现这个技术了。 (关于法线贴图的意义,可见上一篇博客《从“法线贴图的意义

从“法线贴图的意义”到“切线空间公式的推导与验证”

目录 目标1. 法线贴图1.1 “法线”的意义1.2 “法线贴图”的意义 2. 切线空间2.1 法线贴图中数据的含义2.2 “切线空间”的定义 3. 切线空间计算公式3.1 构造几何关系等式3.2 切线空间计算公式 4. 代码5. 验证——与其他美术软件计算的结果进行比较总结 目标 本篇的重点是 讨论法线贴图的意义讨论切线空间的意义推导切线空间的计算公式根据公式编写代码将其计算

【教学类-52-08】20240905动物数独(6宫格)一页2张任务卡,一页一个动物贴图卡,有答案

背景需求: 前文提到6宫格数独的图片6*6=36图,如果将6张任务卡放在一个A4上,看上去6种动物很小,所以我换了一个word模板,变成了2张任务卡放在一个A4上。 【教学类-52-07】20240903动物数独(6宫格)一页2张任务卡,无答案-CSDN博客文章浏览阅读846次,点赞25次,收藏6次。【教学类-52-07】20240903动物数独(6宫格)一页2张任务卡,无答案https:

Three.js new THREE.TextureLoader()纹理贴图使用png图片显示为黑色

问题代码如下: const texture = new THREE.TextureLoader().load('./image.png');droneGeometry = new THREE.PlaneGeometry(1, 1);droneMaterial = new THREE.MeshBasicMaterial({ map: texture});droneMesh = new THRE

探索高速公路位移监测站的科技魅力

在快速发展的现代社会,高速公路作为连接城市与乡村、促进经济交流的重要纽带,其安全性与稳定性直接关系到人民生命财产的安全与交通运输的顺畅。随着科技的进步,高速公路位移监测站作为一种先进的交通基础设施监测手段,正逐渐成为保障道路安全重要的科技哨兵。 一、高速公路位移监测站的重要性 高速公路在长期使用过程中,受到自然环境、车辆荷载、地质条件变化等多重因素的影响,难免会出现路基沉降、边坡滑坡、桥梁位移

【基础】Three.js加载纹理贴图、加载外部gltf格式文件

1. 模型使用纹理贴图 const geometry = new THREE.BoxGeometry(10, 10, 10);const textureLoader = new THREE.TextureLoader(); // 创建纹理贴图加载器const texture = textureLoader.load("/crate.gif"); // 加载纹理贴图const material

17. 位移运算的本质是什么,为什么要有位移运算,作用范围和使用技巧。

1. 位移运算的本质 位移运算(bitwise shift operations)是直接对二进制数的每个位进行操作的运算。通过将数值的二进制位左移或右移,可以快速地完成一些数学运算或位级控制操作。位移运算通常有两种类型: 左移运算(<<):将二进制位向左移动,低位用 0 填充,高位丢弃。右移运算(>>):将二进制位向右移动,具体可以分为两种:算术右移和逻辑右移。 算术右移:保持符号位不变(用于

Unity性能优化之编辑器检查——贴图

优化选项 图片资源一般可做如下优化设置 打包图集mipmap不必要时选择关闭Read/Write Enabled不必要时关闭纹理压缩 图集打包的可以参考Unity性能优化之图集打包;mipmap是多级渐变纹理,Unity会生成多张不同像素的纹理以优化性能,因此不必要时就不要设置mipmap防止增加内存;Read/Write Enabled开启时可能会存在内存拷贝以便io操作,因此尽量不

Unity 动态光照贴图,加载后显示变暗或者变白问题 ReflectionProbe的使用

动态加载光照贴图代码,可参考这个帖子 Unity 预制动态绑定光照贴图遇到变白问题_unity urp 动态加载光照信息 变黑-CSDN博客 这次遇到的问题是,在编辑器下光照贴图能正常显示,打出apk后光照贴图加载后变黑的问题 以下4张图代表4种状态: 左图1:未加载光照贴图 右图2:加载光照贴图后,变黑 出现这个问题,是shader的针对lightmap的变体被剥离的