求知若饥,虚心若愚
图形渲染管线
这里只列出和本节相关的part,详细的可看第一节
- 蓝色背景是渲染管线中可编程部分
- 顶点着色器:一般对顶点携带信息进行加工计算,传递给下一部分着色用。但也可以直接在这里着色,效果和性能视顶点数量而定
- 片元着色器:使用光栅化插值后的信息进行着色(shading)计算,可以做各种复杂着色效果
模型
实现原理
点->线->面->体
UV
- 作用:帮助将一张图无缝贴在任意3d模型的表面,这个过程叫纹理映射。
- 需要将3维物体的表面降维成2d图片,通常会用到拓扑的方法,关键难点是如何无缝衔接。
- uv:上述提到的2d图片展开在一个坐标系中,坐标轴分布为u和v。该坐标通常由建模软件计算并存储在模型文件中。
- 渲染管线通过顶点携带的信息获取,其范围在0-1。表示该3d模型某顶点可以在一张纹理对应的uv坐标采样到某种关联信息。
- 展开后的UV在SP(Subtance Painter)中绘制贴图(漫反射贴图,法线贴图,高度贴图,金属度贴图,AO贴图等)
一个模型包含的信息
以下以OBJ文件为例子
- v:顶点坐标数据(模型空间下xyz坐标)
- vt:纹理坐标(水平方向是U,垂直方向是V,范围0-1之间)
- vn:顶点法线单位向量
- f:面,将每个顶点对应的纹理、法线联系起来,并三个顶点组成一个面。(这里重复利用了相同信息)
- 这些信息都可以在顶点着色器中顶点传入的信息获取
OBJ和FBX格式对比:
材质
为什么需要材质
- 在现实世界里,每个物体会对光产生不同的反应。
- 比如说,钢看起来通常会比陶瓷花瓶更闪闪发光,木头箱子也不会像钢制箱子那样对光产生很强的反射。
- 每个物体对镜面高光也有不同的反应。
- 有些物体反射光的时候不会有太多的散(Scatter),因而产生一个较小的高光点
- 而有些物体则会散射很多,产生一个有着更大半径的高光点
漫反射
- 漫反射是最容易模拟的模型。比如现实中的石头,水泥,砖块等。(光栅模拟简单,但光追时需要发射的光线又是最多的)
- 最简单的Lambertian很简单粗暴的认为光线均匀的反射出去
- 基于物理的话要考虑能量守恒,入射的Radiance和出射的Radiance相等
- BRDF形状理论上应该为半圆
1 | // 提供一个基于URP的简单兰伯特光照模型 |
镜面反射
- 光滑镜面反射。
- 镜面反射就是将入射光线根据表面法线进行反射,并且只有在反射方向有能量,其他方向能量均为0
- BRDF形状为一条直线
- 视角方向越接近出射方向,高光越亮。其中pow函数只是用来拟合,控制高光的大小。
- Blinn-Phong则是计算法线和半程向量的接近程度
1 | // 提供一个基于URP的phong | blinn-phong 光照模型 |
粗糙镜面反射
- 法线偏移较小。反射依然集中在一个区域。
- 形成磨砂的质感
- BRDF为花瓣形状(lobe)
折射
- 对于玻璃这种电介质,除了反射之外还有根据物体的折射率折射一部分光线进入物体之中
- 需要入射介质和进入介质两个折射率,以及对应的角度
- 反射和折射能量的多少是根据菲尼尔(Fresnel)定律决定
- 完整的Fresnel计算通常比较麻烦,实时渲染常用拟合后曲线加速计算
1 | R = refract(View, Normal, ration); |
粗糙镜面折射
- 这种材质在现实中的例子就是各种毛玻璃
- 比起粗糙镜面反射,粗糙镜面折射中有一部分光可以透过去发生折射
多层材质
- 比如涂了清漆的木地板
- 自身的材质+表面新增一层材质叠加
- 单一的微表面BRDF模型很难模拟这种效果
次表面散射
- 半透明的物体。例如玉石、蜡烛、牛奶、皮肤
- 光进入皮肤后与照亮了毛细血管,因此在明暗分界的位置,反射出的红光就更容易被看到
- 详见GAMES101-P18
多层皮肤模型
- 皮肤可以看成三层:油脂,表皮,真皮。
- 油脂层直接把光反射出去,所以皮肤上才出现高光
- 未被反射的光通过折射进入子表面层,进入该层后,部分被吸收和散射
- 再从皮肤中入射点附近出射点射出从而形成次表面散射效果
改变材质表面
- 现实世界中不存在完美平滑的表面,因此需要对模型表面的法线进行扰动。
- 其中一个方法是使用法线贴图。
- 漫反射,高光,折射。都与法线有关,因此改变法线,就能改变其光照计算结果
- 虽然材质特别重要,但是没有一个好的模型,依然不会有好的效果。
- 有时候模型就能表现出它的金属感,布料感。材质在这些基础上就能给人一个更加直观的感受。
- 要在性能和效果之间平衡与取舍
模型数据在渲染中的作用
纹理动画
概念
- UV坐标动画或UV平移的含义是,水平(U)和/或垂直(V)移动纹理的UV坐标,以产生复杂动画的错觉。
- 在渲染管线中,修改模型的UV信息,使得采样贴图时,发生位移而产生运动效果
- 一般出于性能考虑(顶点数和依赖纹理读取),在顶点着色器中偏移uv,片段着色器采样结果
例子
-
光照计算:利用法线贴图,改变反射与折射的朝向。(法线的改变导致反射折射信息计算变换)
-
背面画面采样:改变UV采样点的位置,产生动画效果
顶点动画
- 顶点动画就是在顶点着色器中对模型的顶点进行进行操作(一般是修改位置)进而产生动画效果。
- 顶点着色器计算的是模型的每一个顶点,每个顶点的数据是不同的
- 因此同一个计算公式在不同的顶点上,计算出来的结果也是不同的
- 顶点动画需要一定数量的顶点,效果才会比较明显(可以配合曲面细分着色器)
- 一个顶点传入顶点shader,顶点shader控制顶点位置时,所有的顶点都会进行一样的算法。
- 在一些三维软件中,动画的K帧也是顶点动画
顶点颜色
-
在渲染时,影响输出结果。控制颜色范围
- 可以用来实现顶点色达到一定的值,就做阴影。
- 也可以使用模型的顶点色作为mask使用
-
因四边面在cg软件或者游戏引擎中本质上还是三角面组合而成,所以在绘制时会出现三角形的分界
-
三角形内像素点的色彩会在光栅化时进行插值混合。
- 详细过程可以看GAMES101-P9
- 三角形所在平面任意点(x,y)都可用重心坐标三顶点(α β γ)的线性组合表示
- 重心坐标不能保证投影后不变,所以三维情况下要先找到重心坐标再插值
- 通过当前像素点周围三个顶点的顶点颜色、法线、纹理坐标,进行插值获取当前像素点的对应属性
顶点法线与面法线
不同
- 面法线也是顶点法线,只是存储的方式有所差异
- 当前像素点的法线是通过周围顶点法线插值获得的,而从下图中可以明显看到面法线与顶点法线因为方向不同,插值结果也不同。其中面法线三个点共用一个法线。
原理
- (面法线)未使用平滑时,三角形三个顶点共用一个法线。那么插值时,因为三个顶点的法线相同,所以插值的结果相同。
- (顶点法线)使用平滑后,一个顶点一个法线。三角形三个顶点的法线也就不相同。插值结果,也就会不同。
扩展:NPR中的描边
- 在NPR渲染中。通常在顶点着色器中,将顶点往法线方向偏移。然后再片段着色器中直接输出一个颜色,达到描边的效果。
- BackFacing描边时,线条之间断开就是因为没有使用顶点法线(没有进行平滑着色)
引用
- 课程PPT:https://docs.qq.com/slide/DUUpqWVdnekJIak9I
- LearnOpenGL
- 知乎:文刀秋二(基于物理着色)
- 冯乐乐《Unity Shader 入门精要》
- B站:闫令琪现代计算机图形学入门 GAMES101
- 顶点颜色的使用:https://www.ddove.com/edu/chapter/8123.html
- 大佬笔记: