盘算机图形学编程(使用OpenGL和C++)(第2版)学习笔记 10.加强外貌细节(二)法线贴图

[复制链接]
发表于 2025-8-27 17:46:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1. 法线贴图(Normal Mapping)

法线贴图是一种在3D图形渲染中广泛使用的外貌细节加强技术。它通过存储每个像素的法线信息来模拟外貌的渺小凹凸细节,而无需增加实际的多少复杂度。
1.1. 工作原理


  • 纹理存储

    • 使用RGB通道存储法线向量的XYZ分量
    • 通常出现出偏蓝色的外貌(因为默认法线指向Z轴)
    • 每个像素都包含外貌法线方向信息

  • 切线空间

    • 法线贴图通常在切线空间(TBN空间)中定义
    • 包含切线(Tangent)、副切线(Bitangent)和法线(Normal)
    • 便于将法线信息应用到任意曲面

1.2. 优势



  • 高服从

    • 不增加模子的多边形数目
    • 能够出现出丰富的外貌细节
    • 性能开销相对较小

  • 机动性

    • 可以与其他贴图技术联合使用
    • 适用于静态和动态物体
    • 便于美术人员制作和修改

1.3. 应用场景



  • 游戏角色的皮肤细节
  • 建筑物外貌的砖块纹理
  • 布料的褶皱结果
  • 地形的细节加强
1.4. TBN空间

TBN空间(Tangent Space)是法线贴图中的一个关键概念,它由三个相互垂直的向量构成:切线(Tangent)、副切线(Bitangent)和法线(Normal)。

  • T - 切线(Tangent)

    • 沿着纹理坐标U方向的向量
    • 通常与物体外貌相切
    • 在极点着色器中盘算

  • B - 副切线(Bitangent)

    • 沿着纹理坐标V方向的向量
    • 与切线和法线都垂直
    • 可以通过叉积盘算:B = N × T

  • N - 法线(Normal)

    • 垂直于物体外貌的向量
    • 决定了外貌的朝向
    • 由模子数据提供

1.5. TBN矩阵的作用

  1. // TBN矩阵的构建
  2. mat3 TBN = mat3(T, B, N);
复制代码
主要用途:


  • 将法线贴图中的法线向量从切线空间转换到世界空间
  • 保证法线方向在任意曲面上都正确
  • 使法线贴图可以在不同的外貌上重复使用
1.6. 优势



  • 空间一致性:保证法线方向在任何外貌都能正确体现
  • 可重用性:同一个法线贴图可以应用到不同的模子上
  • 准确性:提供了准确的法线方向盘算
1.7. 实现流程

可以在极点着色器中盘算TBN矩阵,并在片断着色器中应用它,也可以在片断着色器中盘算TBN矩阵。
以下代码展示了如何在片断着色器中盘算TBN矩阵:
  1. layout (binding =0) uniform sampler2D normalMap;    // 法线贴图
  2. //uniform sampler2D heightMap;    // 高度贴图
  3. // 计算法线的函数
  4. // normal: 顶点的法线向量
  5. // tangent: 顶点的切线向量
  6. // texCoord: 纹理坐标
  7. vec3 calcNormal(vec3 normal, vec3 tangent, vec2 texCoord)
  8. {
  9.     // 使用Gram-Schmidt正交化计算切线T
  10.     // 确保切线与法线垂直
  11.     vec3 T = normalize(tangent - dot(tangent, normal) * normal);
  12.    
  13.     // 通过叉积计算副切线B
  14.     // T和N叉积得到B,确保三个向量相互垂直
  15.     vec3 B = normalize(cross(T, normal));
  16.    
  17.     // 从法线贴图中获取法线数据并转换到[-1,1]范围
  18.     vec3 N = normalize(texture(normalMap, texCoord).xyz * 2.0 - 1.0);
  19.    
  20.     // 构建TBN矩阵
  21.     // 用于将切线空间的法线转换到世界空间
  22.     mat3 TBN = mat3(T, B, N);
  23.    
  24.     // 从法线贴图中获取法线数据
  25.     vec3 retrivedNormal = texture(normalMap, texCoord).xyz;
  26.    
  27.     // 将法线从[0,1]范围转换到[-1,1]范围
  28.     retrivedNormal = normalize(retrivedNormal * 2.0 - 1.0);
  29.    
  30.     // 使用TBN矩阵将法线从切线空间转换到世界空间
  31.     vec3 newNormal = normalize(TBN * retrivedNormal);
  32.    
  33.     return newNormal;
  34. }
复制代码
1.8. 进一步阐明切线向量

实际中,切线向量通常由模子数据提供,例如极点法线、极点切线等。这些数据通常存储在模子文件中,例如OBJ文件。
如果模子中没有提供切线向量,就需要通过盘算得到。对于外貌可导的曲面,可以通过盘算得到切线向量。而如果 曲面不可导,就需要使用其他方法来盘算切线向量。一种折中的方式是将每个极点指向下一个极点的向量作为切线向量。但这样会造成极点法线与切线向量不垂直,从而影响法线贴图的结果。因此,在着色器中盘算切线向量时,需要使用一些技巧来保证切线向量与极点法线垂直。
  1. // 确保切线与法线垂直
  2.     vec3 T = normalize(tangent - dot(tangent, normal) * normal);
复制代码
1.9. 法线贴图内容阐明

法线贴图通常由RGB三个通道组成,分别表现法线向量的X、Y、Z分量。每个分量取值范围为[-1,1],但实际文件存贮为[0,1],以是需要经过转换。
  1. // 法线贴图中的法线向量从[0,1]范围转换到[-1,1]范围
  2.   retrivedNormal = normalize(retrivedNormal * 2.0 - 1.0);
复制代码
下图为法线贴图

法线贴图出现蓝色的原因

  • 法线向量的存储方式


  • RGB通道分别对应XYZ轴向
  • 值范围从[-1,1]映射到[0,1]存储
  • 转换公式:color = normal * 0.5 + 0.5

  • 默认法线方向


  • 在切线空间中,默认法线指向Z轴正方向(0,0,1)
  • 转换到[0,1]范围后变为(0.5,0.5,1.0)
  • 这导致蓝色通道(Z轴)的值最大

  • 颜色体现


  • R通道(X)≈0.5:中等红色
  • G通道(Y)≈0.5:中等绿色
  • B通道(Z)≈1.0:最大蓝色
  • 三个通道叠加后出现出偏蓝色的外貌
2. 高度贴图(Height Mapping)

高度贴图是一种使用灰度图来存储外貌高度信息的技术,用于在渲染时动态改变外貌多少形状。

2.1. 工作原理


  • 纹理存储

    • 使用单通道灰度图存储高度信息
    • 黑色(0.0)表现最低点
    • 白色(1.0)表现最高点
    • 灰度值表现中间高度

  • 置换映射

    • 根据高度值沿法线方向移动极点
    • 可以实际改变多少形状
    • 需要较高的网格分辨率

  • 视差映射

    • 不改变实际多少形状
    • 通过调整纹理坐标创造深度错觉
    • 性能消耗较小

2.2. 优势



  • 真实的凹凸结果

    • 可以产生实际的多少变化
    • 在边沿处有正确的轮廓
    • 可以产生自遮挡结果

  • 易于制作和编辑

    • 使用常规图像编辑工具即可创建
    • 直观的黑白高度表现
    • 便于美术人员使用

2.3. 应用示例

  1. // 顶点着色器 中得到的原始顶点位置为vertPos,经过处理后的顶点位置为p
  2. vec3 p=vertPos+ vertNormal*texture(heightMap,vertTexCoord).r*0.2;
复制代码
2.4. 与法线贴图的区别


  • 多少影响

    • 高度贴图可以实际改变多少形状
    • 法线贴图只改变光照盘算

  • 资源消耗

    • 高度贴图需要更多的极点数据
    • 法线贴图主要影响像素着色

  • 结果体现

    • 高度贴图可以产生真实的凹凸轮廓
    • 法线贴图在边沿处结果有限

以下是高度图 (灰度图)

以下是示例中采用的纹理图,为简便起见,只是将高度图加了绿色

3. 参考


  • 学习笔记完备代码下载
  • OpenGL shader开辟实战学习笔记:第十章 法线贴图_法线贴图是什么意思-CSDN博客
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表