快速跳转:
1、矩阵变换原理Transform(旋转、位移、缩放、正交投影、透视投影)
2、光栅化(反走样、傅里叶变换、卷积)
3、着色计算(深度缓存、着色模型、着色频率)
4、纹理映射(重心坐标插值、透视投影矫正、双线性插值MipMap、环境光遮蔽AO)
5、几何(距离函数SDF、点云、贝塞尔曲线、曲面细分、曲面简化)
6、阴影映射(Shadow Mapping)
7、光线追踪原理(线面求交、预处理光追加速)
8、辐射度量学与光线追踪
9、蒙特卡洛路径追踪(Path Tracing)(光源采样)
10、材质(BRDF)(折射、菲涅尔项、微表面模型、各向异性材质)
11、渲染前沿技术介绍(双向路径追踪BDPT、MLT、光子映射、实时辐射度、外观建模)
12、相机(视场、曝光、光圈(F-Stop)、薄棱镜近似、CoC、景深)
13、光场、颜色与感知
14、动画(物理模拟、质点弹簧系统、粒子系统、运动学、动作捕捉、欧拉方法)
lecture07-08
上节课,学习了光栅化,根据三个顶点,绘制一个三角形
绘制多个三角形,涉及到遮挡怎么办?
- 画家算法(对三角形排序)先画远处的三角形,然后近处的三角形覆盖远处
但是这玩意儿不适合在计算机中绘制互相遮挡的图形,如下先画那个三角形?搞不定
1 Z-buffer深度缓存
- 不对三角形进行排序,在每个像素上对z值 比大小
- 用一块缓存,存放每个像素的深度信息
- 得到最终渲染图像的同时会有一个深度缓存产生
1、frame buffer 存放每个像素的颜色
2、depth buffer 存放每个像素的深度信息(也叫z-buffer) - 注意相机看向-z轴,为了方便计算对z轴数值取绝对值,z越大越远
- 建立深度缓存的方法
-先建立一个深度缓存,其实就是个二维数组zbuffer[width][height],并且初始化每个数组元素为无穷
-遍历每个三角形所覆盖的每个像素,将该像素所对应的场景中的那个点的z值跟zbuffer对应位置的z作比较,小则覆盖 - 输入的是三个顶点,怎么知道三角形覆盖的某个像素存的z值是多少? —重心坐标插值
- 代码表述
- 图形示例
- 另外,如果采用MSAA抗锯齿,则深度缓存不再每个像素存一个z,而是对每个采样点存放一个深度
- 至此已经可以在屏幕上画出各种三角形组成的有遮挡的模型,如下图(左)
- 但是这图也太假了,我们想要的是下图(右)这种根据光源的位置/夹角,模型表面颜色会有明暗不同
2 Shading着色
- 着色:对不同物体应用不同的材质
- 计算着色的玩意儿叫shader(着色器)
- 以下着色计算都是考虑在一个点上进行计算,要应用到整个模型,则需要在所有点上进行着色计算
2.1 Phong / Blinn-Phong 着色模型
- 某个光源下,物体表面反射出三种不同的状态
漫反射、高光、环境光
- 计算物体表面某个点的着色需要以下定义
需要提醒的是v、n、l 方向向量都是单位向量
Surface parameters:表面属性,定义该点的颜色、高光度、粗糙度等等。
2.1.1 Diffuse Reflection漫反射
- 光线打到物体表面某个点,会被均匀地反射到四面八方
- 为什么光照到物体上,同一个表面的不同点表现出明暗不同?
因为每个点接受到的光的能量不同,每个点其实微观上是一个平面 - 如何计算一个单位面积(点)收到多少能量?
(1) 光线与该点法线的夹角大小不同,接收到能量不同
夹角θ越大,cosθ越小,接收到的光线(能量)越少,即收到的能量与cosθ成正比 cosθ = l · n
(2) 光线传播本身会衰减
假设光是均匀发散出去,则在发射出去的一个球面上的光密度跟传播长度r成反比
定义光在传播到单位距离的时候,强度是I,则传播到r处时的能量 = I / r2
- 最终一个点上的漫反射光强度(经验公式)
Ld = kd(I/r2)max(0,n·l) - 注意物体表面接收到能量后,均匀的向四面八方发射,所以与观察角度无关(不管什么角度看过去都是一样的结果),
- kd就是三通道的颜色值
- 在一个石膏球上进行漫反射计算的结果
看单个球体随着光源跟法线夹角逐渐变大,颜色会越来越暗
从左到右每个球体的kd值越来越大,
2.1.2 Specular高光
在已经计算完物体的漫反射的基础上,加入高光。
注意:反射(能看见高光的接近镜面反射)和漫反射是同时发生的,只是计算方式不同,分开讨论
-
什么情况下能看到高光?
高光一般产生在比较光滑的物体上,类似镜子、玻璃、光滑的头。。。
绝对光滑的物体的镜面反射那就只能在R这 一个方向看到高光,别的任何角度、方向都是看不到的
但只要稍微不那么光滑,那我们将能在镜面反射方向的附近一个小区域内可看见高光
所以v和R足够接近的时候能看见高光
但是如果对v和R的接近程度进行判断,我们就必须算反射方向R,麻烦(Phong模型就是算R,判v·R) -
Blinn-Phong方法:
利用半程向量与法向量的点积来判断高光程度
这种方法,好在舍弃掉了镜面反射方向R,半程向量h特别好算,光线入射方向+视线方向,再化单位向量即可,再利用公式算出高光强度Ls就行,这个高光计算公式跟漫反射的没多大区别
-
为啥考虑了光线的衰减(I/r2),但没考虑吸收了多少光呢(n·l)?
经验模型,意思意思就行了,怎么方便怎么来 -
为啥最后p次方?
为了让衰减速率变得快些让高光范围变小,比如我视线偏离镜面反射角度都快45度了还能看到高光,不行吧。
-
ks是镜面反射系数,p是高光范围控制
2.1.3 Ambient环境光
- 环境光真要计算得真实的话就太复杂了,Bulinn-Phong着色模型计算中,环境光直接是一个常数仅仅是保证模型没有纯黑的地方(多少有点光照上去吧)
- 给光照强度乘个系数ka,用这个系数控制环境光强度La
- 最终的Blinn-Phong反射模型
前面的讨论都是对物体某一个点进行的计算,最终要对物体所有的点应用后(不一定是所有的点哦,计算量太大了),得到完整的渲染结果
2.2 Shading Frequencies着色频率
学会了布林冯着色模型的对点的着色计算方式
接下来就该考虑到底以什么样的一个频率去应用,或者说到底要对哪些点进行计算?
每个像素算一次?每个三角形的顶点算一次?
- 以下图形就是着色频率不同,最终效果的差异分别是:
(1)面着色,一个平面计算一次,计算结果应用给该平面的每个点
(2)顶点着色,每个顶点都计算一次,然后面内点做插值
(3)像素着色,算出每个顶点法线,对法线进行插值得到面内每个像素的法线,再做着色计算
2.2.1 Flat Shading面着色
- 面着色,每个面只有一个法线,进行一次着色计算,应用到该面内所有像素
所以每个面内部的颜色(明暗)没有差异
2.2.2 Vertex Shading顶点着色
- 算出每个顶点的法线,然后对每个顶点计算着色,最后把着色结果插值得到三角形内部的颜色值
每个面的法线好算,通过任意两个边做个叉乘就行 - 那每个顶点的法线怎么算?—— 没必要算,也不用算,三角形每个顶点都有自己法线。
若没定义顶点法线,单单一个顶点是算不出法线的,必须通过该点相邻的三角面的法线做个平均或者加权平均
Nv = (N1+N2+N3+N4)/4
2.2.3 Pixel Shading
通过重心坐标计算得到每个像素的法线,然后对每个像素计算着色
注意:Phong Shading != Blinn-Phong反射模型是完全不同的东西
3 Graphics Pipeline图形管线
渲染管线:把一个场景经过一系列的处理,最后再显示器上显示一张图像,这一系列过程就叫渲染管线
虽然不够详细,但是流程大概可以描述为以下几个阶段
1、输入一堆三维空间中的点
2、经过MVPV变换后得到这些点在屏幕上的二维坐标
3、规定哪些点相互构成三角形(指定图元拓扑结构)
4、光栅化,得到被三角形覆盖的像素
5、着色计算,计算每个像素该显示什么,应该是什么颜色,Z-buffer的生成等
6、把计算结果存到一个缓存中,输出到显示器。
- 渲染管线大致流程可以是下面这样但不绝对,比如着色可以在顶点处理的阶段进行,具体的要看程序员怎么搞了。
- 目前硬件开放给程序员的可编程部分为VertexProcessing和Fragment Processing,即计算每个顶点或者像素的着色,这部分代码就叫做着色器(shader)
4 shader
着色器:就是一段代码,这段代码是在硬件上执行的,定义了如何计算一个顶点或者像素。
顶点着色器:处理顶点
像素着色器:处理像素
- 以下代码是OpenGL 中的GLSL着色器语言写的像素着色器代码
这段代码的功能是对输入的像素映射纹理,并且计算出漫反射项,最后给这个像素的颜色赋值
- 到此为止,对渲染管线已经有个基本的认识了
暂无评论内容