图形学基础 (五) 着色及着色频率

画家算法

对于一个人他在绘图的过程中一般是先画远处的, 再用近处的物体覆盖, 计算机中也是这样

image-20211206082318708

假如我有这样一个正方体, 怎么把它绘制到屏幕上呢? 也即如何把它光栅化, 我可以先画后面的边, 再画左边的, 再画右边的, 这里存在的问题是我无法知道绘图的顺序, 这个表示远近应该怎么解决呢?

在这里插入图片描述

  • 这里一个朴素的思想是把所有的物体深度都排序, 然后按顺序绘制, 但是这里的前提是每个物体的深度都是规则的, 只有越来越大或者越来越小, 所以遇到下面的图就不行了, 下图中两两重叠, 不能单独说谁更近谁更远

在这里插入图片描述

### Z-Buffer

  • 因为对空间中的三角形不容易排序, 那就对每个像素排序, 那么这个时候我们需要一个深度图或者说深度缓存, 它存了每个像素的深度信息

image-20211206090905957

frame buffer就是生成的结果, 另一个就是深度buffer, 如下图:

  • 深度越小越黑,反之变白

image-20211206091810049

  • 之前的时候我们规定了相机朝向是-z, 也就是z越小就越远, 数字大就离相机越近

现在在深度中我们同样有这个z表示距相机的距离, z越小代表越近

在这里插入图片描述

深度缓存算法
  • 假设一开始所有像素的深度都是无限远的

  • 对每个三角形的每个像素, 假如它比之前这个位置的深度小(深度小就代表距离近, z都是正的),就把它替换之前的

在这里插入图片描述

  • 下面这个图就很直观的表明了我的整个过程, 图上的数字表示深度, 红蓝表示RGB值

image-20211206092731374

  • 这种算法是和绘制的顺序无关的

着色(Shading)

目前学到的有经过一些变换从三维顶点得到了二维顶点, 然后二维顶点可以连接成三角形进行光栅化

在这里插入图片描述

在图形学中着色可以理解成对不同物体应用不同的材质, 比如金属球, 木球, 它们和光线有不同的交互

Blinn-Phong Reflectance Model
  • 这是最简单的着色模型

在这里插入图片描述

假设光源在右上, 有镜面导致的高光, 有漫反射, 有环境光

  • 对于一个要着色的点我把它微分为平面, 当作平面来处理

v是观测方向, I 是光照方向, n 是法线方向, 既然指的是方向, 那么这几个都是单位向量

在这里插入图片描述

表面的参数比如有 shininess, color …

这里的着色不包括阴影, 不考虑其他物体的存在,只考虑一个点

在这里插入图片描述

漫反射

光线均匀的反射到各个方向上

image-20211206095916152

不同的角度漫反射接收到的能量不同

在这里插入图片描述

光源假设为点光源, 辐射出的能量按球壳出现, 每个球壳的能量一致, 球壳越大, 单位面积能量越小, 大致是个平方关系

S = 4 Π r 2 S=4Π r^2 S=4Πr2

在这里插入图片描述

每个点的光强关系如下, I I I 是单位长度的光强, 接受的多少取决于角度的cos值 , 负数的时候无意义, 因为相当于光线从下面过来

在这里插入图片描述

  • kd 是漫反射系数, 代表这个点吸收多少光, 因为不同的材质对光的吸收是不一样的, 假如是1就代表完全不吸收, 假如是0就全吸收了, 这个点就是黑色了
  • 假如是个三通道的RGB值, 就可以定义一个三维的kd了
  • 这里注意漫反射是和入射角有关的, 只不过和你的观察角度无关, 也就是和v无关

查看kd的影响:

在这里插入图片描述

Specular Term (镜面反射, 高光项)
  • 什么时候能看到这个高光呢? 很容易想到, 当我的观察方向和出射方向差不多的时候可以看到. 也就是观察方向 v 和 反射方向 R 接近

在这里插入图片描述

  • Blinn-Phong 模型做了改进, 不是衡量 v和R, 而是衡量 法线 n 和 半程向量 h, 所谓的半程向量如下, 就是光线入射方向和观察方向求和然后单位化为 单位向量, 就是一个中间方向

在这里插入图片描述

假如n 和 h接近就相当于 v和R接近, 接近程度用cos的幂表示

在这里插入图片描述

在这里插入图片描述

  • 为什么用幂呢? 因为高光的话偏离一点就看不到了, 所以衡量接近程度需要用幂, 如下图:

在这里插入图片描述

这样就减少了角度, 看下面这个例子, 横向随着幂次p越来越大 ,镜面反射接近一个点

在这里插入图片描述

Ambient Term (环境光照项)
  • 环境光是四面八方的, 每个点接收到的环境光是相同的, 每个像素点有个环境光系数

在这里插入图片描述

综合
  • 现在综合环境光, 漫反射光, 镜面反射光得到了最后的结果

在这里插入图片描述

着色频率 (shading Frequencies)

1. flat shading

在这里插入图片描述

对于每个三角形求解其法线, 两个边叉乘就行, 每个三角形都是同样的像素

2. Gouraud shading (高洛德着色)
  • 这里假设三角形每个顶点的法线可以求出来, 那么三角形中间的像素值通过插值得到

在这里插入图片描述

3. Phong shading
  • 这是对每个像素求个法线, 是求出顶点的法线后对其余像素做插值求法线
  • 对每个像素进行着色

在这里插入图片描述

4. 着色频率的探讨
  • Phone 着色模型一定比Gouraud 方式要好吗 , 这不见得,比如下面每列是不同的着色方式, 会法线随着三角形面片的增加, flat shading 也可以有很好的效果

在这里插入图片描述

怎么求出顶点的法线呢

一个顶点会和周围的三角形有联系, 在这里, 一个顶点的法线是其他面片的法线的平均, 但是这里不是直接的平均, 而是按面积加权的平均

在这里插入图片描述

  • 现在假设我已经知道了顶点的法线, 那么如何计算三角形内部像素的法线呢?下面的图上我知道了左右两边顶点的法线, 然后通过某种方法得到中间像素渐变的法线

在这里插入图片描述

需要借助重心坐标得出

不要忘了归一化, 因为法线是个方向

Graphics pipeline (Real time Rendering) 实时渲染管线

三维空间的点投影到平面, 然后形成三角形, 光栅化为不同的像素, 进行着色, 最后输出图片

在这里插入图片描述

  • 在这里有两种定义是一样, 一个是定义模型的顶点和三角形, 一个是只定义顶点, 三角形在顶点投影后再计算, 这里三角形是不会变的,因为只是坐标变了相对位置没变

下面逐个解释

顶点处理对应的是坐标系的变换

在这里插入图片描述

在这里插入图片描述

  • 下面是三角形光栅化, 也就是得到那些像素应该显示在屏幕上

在这里插入图片描述

在这里插入图片描述

  • 经过光栅化产生一系列的像素或者说fragment 后,判断每个像素是否可见, 使用z-buffer

在这里插入图片描述

在这里插入图片描述

  • 最后是着色, 发生在顶点和像素上, 假如是高洛德着色那就是顶点, Phong 着色就是对像素着色

在这里插入图片描述

Texture mapping (纹理映射)

  • 看下面这个三角形, 每个顶点对应不同的属性, 就是说每个点的木头纹理不同, 做到这件事就是纹理映射

在这里插入图片描述

或者看下面这个图, 对于这个球来说它就是两个点光源相加, 但是有的地方红, 有的地方蓝,说明它有不同的漫反射系数, 定义任意一个点的不同属性比如颜色啥的, 就是这个texture , 比如3DMM中的RGB

在这里插入图片描述

理解怎么定义点的不同属性
  • 具体是定义在哪呢? 是定义在物体的表面上, 物体表面又怎么去理解呢?

对于下面的图, 它可以展开成2维的, 也就是说对于一个三维的物体它可以展开为2维的表面, 这个就是texture, 把这个再包回去, 就是texture mapping

在这里插入图片描述

又比如下面的图, 假如我三维模型中的三角形可以在二维的texture中找到对应的三角形, 这就可以实现映射了

在这里插入图片描述

具体怎么把空间中的三角形映射到纹理上我们不去管,我们认为已经有了这样一个映射关系, 下面关注下纹理上的坐标是啥呢?

  • 纹理上的坐标系是uv坐标系
  • uv的范围约定在0~1之内

Shader Programs (着色编程)

shader 分为顶底shader 和像素或者说fragment shader, 这个shader是通用的

  • 如果是顶点着色器就叫vertex shader, 如果是像素着色器就叫做fragment shader, 也有的翻译成片段着色器, 其实就是像素着色器

  • 像素着色器其实是得到像素最后的颜色并输出

    下面是一个简单的openGL 的 GLSL语言写的小着色器:

在这里插入图片描述

首先定义了texture, lightdir, uv, norm, 具体操作是先得到漫反射系数kd, 然后再求解夹角, 这里有个负号, 其实是定义光线入射方向时导致的, 之前提到的入射方向朝外, 在这里是向里, 所以加了个负号

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

live_for_myself

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值