【Unity Shader入门精要】— 写Shader所需的数学基础

来源:互联网 发布:mysql constraint 编辑:程序博客网 时间:2024/05/22 12:50

内容会持续更新,有错误的地方欢迎指正,谢谢!

引言

一些很简单的线性代数的基本知识:矢量和矩阵。So Easy~

笛卡尔坐标系

两种三维坐标系:左手坐标系和右手坐标系。
这里写图片描述
这里写图片描述

在Unity中:
对于模型空间和世界空间,使用的是左手坐标系;对于观察空间,使用的是右手坐标系。

点和矢量

单位矢量:

法线方向、光源方向等矢量不一定是归一化后的矢量,由于我们的计算往往要求矢量为单位矢量,因此,在使用前要对这些矢量进行归一化运算。

矢量的点积:

公式一:a Dot b=axbx+ayby+azbz
公式二:a Dot b=|a||b|cos(角度)
代码:dot(a,b)
点积在图形学中用得很多,其几何意义很重要,其中一个几何意义:投影(也就是一条边投影到另一条边的长度)。

矢量的叉积:

公式一:a × b=(aybz-azby , azbx-axbz , axby-aybx)
得到的结果是一个垂直于矢量a和b所在的平面的矢量。
公式二:|a × b|=|a||b|sin(角度)
叉积在图形学中常用于计算垂直于一个三角面的矢量,用于判断三角面片的朝向等。

矩阵

**矩阵乘法:**m×n的矩阵 乘以 n×p的矩阵 等于 m×p的矩阵:
这里写图片描述

一个矩阵可以把一个矢量从一个坐标空间转换到另一个坐标空间。

特殊矩阵:

  1. 方块矩阵:简称方阵,就是行和列相等的矩阵。除对角线上的元素的其他元素都是0,则是对角矩阵。
  2. 单位矩阵:对角线元素都是1的对角矩阵就是单位矩阵。
  3. 转置矩阵:行列互换,右上角加T。
    这里写图片描述
  4. 逆矩阵:方阵才有逆矩阵,右上角加-1。
    这里写图片描述
    这里写图片描述
  5. 正交矩阵:矩阵M和它的转置矩阵的乘积是单位矩阵。公式为:
    这里写图片描述
    这个公式很有用,因为求解一个矩阵的逆矩阵计算量很大,但转置矩阵很容易,所以如果我们知道该矩阵是正交矩阵,那用转置矩阵就可以当逆矩阵了。
    正交矩阵的行与行之间,列与列之间分别构成了一组标准正交基。任何三个彼此垂直长度都是1的向量都是一组标准正交基。
    这在空间转换中很有用,如果这些基矢量是一组标准正交基的话,那我们就可以直接用其转置矩阵来得到其逆矩阵了。
  6. 行矩阵和列矩阵
    在Unity中,常规做法是把矢量放在矩阵的右边,即Mv。例如:
    CBAv = (C(B(Av)))
    表示先对v使用A变换,再用B变换,再用C变换,是从右往左的顺序。所以如无特殊情况,我们往往使用向量的列矩阵表达式。

矩阵的几何意义:变换

在计算机图形学中,矩阵的变换特别重要,包含:旋转、缩放和平移。

齐次坐标

3x3的矩阵不能表示平移操作,我们扩展到4x4,这个四维矢量就是齐次坐标。那如何把三维矢量转换成齐次坐标:对于点,把w分量也就是第四维设为1;对于方向矢量,w分量设为0。

几种基础变换矩阵

对一个点,我们用4x4矩阵对其平移、旋转、缩放都可以。但对于方向矢量,平移效果没用,因为方向矢量我们只关心其方向和大小,位置没有意义,故对方向矢量使用3×3的矩阵。

平移矩阵:平移矩阵的逆矩阵就是反向平移得到的矩阵=>平移矩阵不是正交矩阵。
这里写图片描述
缩放矩阵:缩放矩阵的逆矩阵就是k全部变成1/k=>缩放矩阵不是正交矩阵。
这里写图片描述
旋转矩阵:旋转矩阵的逆矩阵是旋转相反角度得到的变换矩阵。把下面的 这里写图片描述 用 —这里写图片描述 代替求出的矩阵就是其逆矩阵,然后你会发现其逆矩阵和其转置矩阵一样,所以旋转矩阵是正交矩阵。
这里写图片描述
复合变换:
这里写图片描述
从右往左逐一变换,即按照缩放,旋转,平移的顺序,变换顺序很重要。

坐标空间

使用上一节学习的矩阵变换来对坐标空间进行变换。不同的坐标空间有着不同的用途,所以,渲染会使用很多坐标空间。

模型顶点的坐标空间的变换过程

顶点被渲染到屏幕的流程都发生在渲染的几何阶段,具体流程:
模型空间—>世界空间—>观察空间—>裁剪空间—>屏幕空间

模型空间

扩展到齐次坐标。

世界空间

这里写图片描述

观察空间

同样是先求变换矩阵M,再用变换矩阵M去乘以世界空间的坐标,得到观察空间的坐标。

裁剪空间

视锥体决定摄像机能看到的空间,由6个裁剪平面构成。视锥体有两种类型:
1.透视投影:地面的平行线并不会保持平行,离摄像机越近网格越大;2.正交投影:所有网格大小都一样,平行线会保持平行。
所以,透视投影模拟了人眼看世界的方式,适合3D游戏,而正交投影则完全保留了物体的距离和角度,适合2D游戏。

这6个裁剪平面中有两个比较特殊:近裁剪平面和远裁剪平面。它们决定了摄像机可以看到的深度范围。
这里写图片描述

如果直接用视锥体定义的空间来进行裁剪,那么不同的视锥体要不同的处理,而且透视投影的视锥体判断起来更麻烦。所以我们需要一种更通用的方式,通过一个投影矩阵把顶点转移到一个裁剪空间中。

投影矩阵有两个目的:

第一,为投影做准备
投影矩阵并没有进行真正的投影工作,而是为后面真正的投影做准备。投影是个降维的过程,从三维降到二维,真正的投影发生在后面的屏幕映射中,通过齐次除法获得二维坐标。

第二,对x、y、z分量进行缩放。
直接用视锥体的6个裁剪平面进行裁剪比较麻烦。经过投影矩阵缩放后,w分量会成为一个范围值,如果x、y、z都在这个范围内,就说明顶点位于裁剪空间中。

下面,我们分别看看两种投影类型的投影矩阵:
一、透视投影

透视摄像机的参数对透视投影视锥体的影响 :
这里写图片描述

同样是先求变换矩阵M,再用变换矩阵M去乘以观察空间的坐标,得到裁剪空间的坐标。

二、正交投影

正交摄像机的参数对正交投影视锥体的影响 :
这里写图片描述

同样是先求变换矩阵M,再用变换矩阵M去乘以观察空间的坐标,得到裁剪空间的坐标。

屏幕空间

经过投影矩阵变换后,我们完成了裁剪工作,开始正式投影了,把视锥体投影到2D的屏幕空间。

屏幕空间是个二维空间,投影的过程分为两步:

  1. 首先,要进行齐次除法。就是用x、y、z分量除以w分量。在OpenGL中,这一步得到的坐标叫归一化的设备坐标(NDC,Normalized Device Coordinates)。经过这一步,我们把坐标从齐次裁剪空间转换到NDC中,你会惊奇的发现,这样会使透视投影的类似金字塔形状的空间变成正方体,并且和正交投影的一样:
    这里写图片描述
    这里写图片描述
    透视投影坐标经裁剪矩阵变换后w是-z,所以坐标x、y、z都除以-z就得到了右边的样子。而正交投影变换后w是1,所以除以1没变化,这样两种投影方式就都是一样的正方体了。

  2. 开始屏幕映射:
    Unity左下角坐标是(0, 0),右上角是(pixelWidth, pixelHeight),现在经过齐次除法后x、y(这里的x,y都是裁剪空间的坐标除以w后的x,y)的范围是[-1, 1],所以这个过程就是个缩放的过程。首先把x、y变到[0, 1],很简单,比如x = (x + 1) / 2,然后再乘以pixelWidth就是映射后的x了,总公式如下:
    这里写图片描述

总结:

顶点着色器的最基本的任务就是把顶点坐标从模型空间转换到裁剪空间中。也就是前三个顶点变换的过程。后面的变换(从裁剪空间到屏幕空间)是Unity自动完成的。然后在片元着色器中,我们就可以得到该片元在屏幕空间的像素位置了。最后上一张图总结一下:

渲染流水线中顶点的空间变换过程 :
这里写图片描述

Unity中各个坐标空间的旋向性 :
这里写图片描述

Unity Shader的内置变量(数学篇)

没必要去记,用的时候查表即可。

1)变换矩阵
这里写图片描述

2)摄像机和屏幕参数
这里写图片描述

补充

视口坐标=屏幕坐标/屏幕分辨率。
视口坐标很简单,就是把屏幕归一化。因此,视口坐标中,屏幕左下角就是(0,0),右上角就是(1,1)。

Unity Shader数学篇到此结束~

阅读全文
0 0
原创粉丝点击