计算机图形学【GAMES-101】3、着色计算(深度缓存、着色模型、着色频率)

快速跳转:
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、动画(物理模拟、质点弹簧系统、粒子系统、运动学、动作捕捉、欧拉方法)


上节课,学习了光栅化,根据三个顶点,绘制一个三角形

绘制多个三角形,涉及到遮挡怎么办?

  • 画家算法(对三角形排序)先画远处的三角形,然后近处的三角形覆盖远处
    但是这玩意儿不适合在计算机中绘制互相遮挡的图形,如下先画那个三角形?搞不定
    在这里插入图片描述

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着色器语言写的像素着色器代码
    这段代码的功能是对输入的像素映射纹理,并且计算出漫反射项,最后给这个像素的颜色赋值
    在这里插入图片描述
  • 到此为止,对渲染管线已经有个基本的认识了

GAMES101图形学专栏

© 版权声明
THE END
喜欢就支持一下吧
点赞950 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容