【learnOpenGL】凹凸映射+Qt做的小Demo

一、凹凸映射原理

凹凸映射[1]

主要用来模拟物体表面几何形状的凹凸起伏。其基本思想是通过扰动表面法向量,使得物体表面受光线照射的影响而产生视觉的变化,进而引起外观的改变,也就是生成视觉上假的凹凸效果。

步骤

  1. 对输入的光滑表面计算法向量,并通过随机扰动改变法向。
  2. 使用新的法向替代原始光滑表面的法向,计算新的光照效果。

​ 通常在第2步中采用局部着色技术(eg. Phong着色模型),就可以得到具有明显凹凸效果的物体外观。
在这里插入图片描述

法线贴图

每个fragment使用各自的法线,替代插值表面法线,并使用2D纹理来储存法线数据的技术叫做法线贴图(normal mapping)或凹凸贴图(bump mapping)。

法线方向的分量范围在 [ − 1 , 1 ] [-1,1] [1,1],而像素范围为 [ 0 , 1 ] [0,1] [0,1]。因此,在shader中得到法线纹理的像素值后,需要做一个映射 n o r m a l = p i x c e l × 2 − 1 normal=pixcel\times 2-1 normal=pixcel×21,并归一化。

切线空间(tangent space)

法线贴图中的法线向量定义在切线空间中,在切线空间,三角面的切线永远指向 z z z方向。切线空间是位于三角形表面之上的空间——法线相对于单个三角形的本地参考坐标系。
在这里插入图片描述

TBN矩阵

TBN矩阵是一个基底变化矩阵,可以把切线空间的向量转变到世界坐标。构建TBN矩阵的三个向量:tangent(切线)、bitangent(副切线)和normal向量。

已知三角形的顶点和纹理坐标,可以计算得到tangent(切线)和bitangent(副切线)向量:
在这里插入图片描述

根据三角形顶点坐标,可求得边向量 E 1 E_1 E1 E 2 E_2 E2,而
E 1 = Δ U 1 T + Δ V 1 B E 2 = Δ U 2 T + Δ V 2 B E_1=\Delta U_1T+\Delta V_1B\\ E_2=\Delta U_2T+\Delta V_2B E1=ΔU1T+ΔV1BE2=ΔU2T+ΔV2B
解得(详细求解见[2])
[ T x T y T z B x B y B z ] = 1 Δ U 1 Δ V 2 − Δ U 2 Δ V 1 [ Δ V 2 − Δ V 1 − Δ U 2 Δ U 1 ] [ E 1 x E 1 y E 1 z E 2 x E 2 y E 2 z ] \begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix} =\frac{1}{\Delta{U_1}\Delta{V_2}-\Delta{U_2}\Delta{V_1}} \begin{bmatrix} \Delta{V_2} & -\Delta{V_1} \\ -\Delta{U_2} & \Delta{U_1} \end{bmatrix} \begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix} [TxBxTyByTzBz]=ΔU1ΔV2ΔU2ΔV11[ΔV2ΔU2ΔV1ΔU1][E1xE2xE1yE2yE1zE2z]

  • 如何使用TBN矩阵?

    • 方案1:直接使用,把切线空间向量转换到世界坐标。把TBN矩阵传到fragment shader,采样得到的法线左乘上TBN矩阵,将法线转换到世界坐标空间,这样所有法线和其他光照变量就在同一个坐标系中了。
    • 方案2:使用TBN矩阵的逆矩阵,把世界坐标空间的向量转换到切线空间。使用这个矩阵左乘其他光照变量,把他们转换到切线空间,这样法线和其他光照变量再一次在一个坐标系中了。

    方案1实现起来简单,但是每个fragment都要将采样法线的转换到世界空间;而方案2只需要在vertex shader中将光照变量转换到切线空间即可,不需要每个fragment都计算一遍。所以本实验的做法是在vertex shader中计算切线空间的光照变量,发送到fragment shader。

视差贴图

高度贴图(Height Mapping),又名视差贴图(Parallax Mapping),模拟表面位移(Displacement),存储的是表面模型局部海拔高度的强度值(Intensity),颜色越深越凹,颜色越浅越凸。视差贴图背后的思想是根据观察方向和高度贴图修改纹理坐标,使一个fragment的表面看起来比实际的更高或者更低(利用高低信息实现遮挡效果)。

  • 优点:直观展示模型表面的凹凸
  • 缺点:实时计算时需要计算像素灰度值来得到法线信息,十分消耗性能。实际应用中,高度贴图通常与法线贴图一起使用,用于给出表面凹凸的额外信息。
原理

下图中, V ˉ \bar V Vˉ是观察方向,与模型平面相交于 A A A,此时观察者看到的是点 A A A,如果应用凹凸贴图,观察者本应看到的是点 B B B。视差贴图的目的就是在 A A A位置上的fragment不再使用点 A A A的纹理坐标而是使用点 B B B的。
在这里插入图片描述
如何得到 B B B的纹理坐标?

视差贴图通过对从fragment到观察者的方向向量 V ˉ \bar{V} Vˉ进行缩放的方式解决这个问题,缩放的大小是 A A A处fragment的高度 H ( A ) H(A) H(A),得到经缩放的向量 P ˉ \bar{P} Pˉ。这里使用切线空间下的 V ˉ \bar{V} Vˉ,这样 P ˉ \bar{P} Pˉ x x x y y y坐标值对应的就是相对于 A A A的纹理坐标偏移量。

陡峭视差映射

陡峭视差映射(Steep Parallax Mapping)通过增加采样数量提高精确性,是视差映射的扩展,采用多个样本来确定纹理偏移,即使在高度变化陡峭的情况下,也能得到不错的效果。其原理如图,将总深度范围划分为多个层,沿 P ˉ \bar{P} Pˉ逐层前进移动采样纹理坐标,直到我们找到一个采样低于当前层的深度值。

https://gitee.com/mostig/csdn-image/raw/master/data/image-20220501155239069.png
陡峭视差贴图同样有自己的问题。因为这个技术是基于有限的样本数量的,我们会遇到锯齿效果以及图层之间有明显的断层。可以通过增加样本的方式减少这个问题,但是很快就会花费很多性能。有些旨在修复这个问题的方法:在两个接近的深度层进行插值找出更匹配的 B B B,比如Relief Parallax Mapping和Parallax Occlusion Mapping。

视差遮蔽映射

视差遮蔽映射(Parallax Occlusion Mapping)和陡峭视差映射的原则相同,但不是用触碰的第一个深度层的纹理坐标,而是在触碰之前和之后,在深度层之间进行线性插值。

二、Demo功能(Qt+OpenGL)

Demo地址:https://github.com/messymorse/Parallax-Mapping-Demo

  • 点击“凹凸映射 Demo”按钮:加载凹凸映射Demo
    • 法线贴图(Normal Mapping)
    • 视差贴图(Parallax Mapping)
    • 陡峭视差映射(Steep Parallax Mapping)
    • 视差遮蔽映射(Parallax Occlusion Mapping)
  • 读取obj格式的mesh文件(支持漫反射贴图、光照贴图和法线贴图)
  • 交互
    • 拖动滑块控制模型旋转

    • 控制相机移动

      • 【W】【S】【A】【D】【Shift】【Space】进行前、后、左、右、上、下平移
      • 鼠标滚轮zoom in/out
      • 鼠标右键拖动视角

三、程序的输入输出格式

本次实验以长方形Mesh为例,其各个属性(位置Positions,法线normal,纹理TexCoords)在程序中给出。

输入:diffuse贴图,normal贴图,height贴图

输出:凹凸映射下的模型

四、参数的含义

程序可设置参数如图,具体说明如下:

  • Rotate:模型绕轴(1,0,1)旋转的角度
  • Normal Mapping:使用“normal_mapping”shader
  • Parallax Mapping:使用“parallax_mapping”shader的普通视差贴图模式
  • Deep Parallax Mapping:使用“parallax_mapping”shader的陡峭视差贴图模式
  • Parallax Occlusion Mapping:使用“parallax_mapping”shader的视差遮蔽贴图模式
    在这里插入图片描述

五、典型的效果

  1. 程序运行界面,其中白色方块是光源位置
    https://gitee.com/mostig/csdn-image/raw/master/data/image-20220501162151810.png

  2. 无凹凸映射、Normal Mapping和Parallax Mapping对比(Blinn-Phong光照模型下)

    左、中、右图分别是使用diffuse map、diffuse map + normal map和使用diffuse map + normal map + height map的效果

在这里插入图片描述
在这里插入图片描述

  1. 视差贴图、陡峭视差贴图和视差遮蔽贴图对比

在这里插入图片描述

六、分析优缺点

优点

  • 包括法线贴图、视差贴图(基础视差贴图、陡峭视差映射、视差遮蔽映射)多种凹凸映射技术
  • 可通过交互界面快捷地切换不同凹凸映射,拖动滑条旋转模型观察不同角度光照下的效果

缺点

  • 只实现了基于平面的凹凸映射,对于网格模型只实现了法线贴图,这也是由于本程序只支持加载obj格式的模型,而一般obj模型不包含视差贴图。

Reference

[1]《现代计算机图形学基础》黄华

[2] OpenGL 教程 https://learnopengl-cn.github.io/ & https://learnopengl.com/Introduction

[3] OpenGL Qt实现入门篇 https://www.bilibili.com/video/BV1UL411W71w?spm_id_from=333.999.0.0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值