webgl编程指南_webgl系列 第一章基础数学知识

前言

从第一次接触threejs开始,到现在也已经过去2年多时间了,从一开始对3D的恐惧,到慢慢能做出一些东西,深深的感受到3D这一块的对综合知识能力的要求之高,特别是对于一个信息安全专业的学生而言,之前从未接触过任何图形学相关的内容,各种术语和GLSL的陌生感让人感到那么无力。

虽然threejs确实封装的很好,也提供了各种材质/灯光的封装,但是当看到各种神奇的效果的时候还是会一脸懵逼,不知道如何实现,看到shader代码也完全看不懂,那感觉...就特别失落。

d1fe009e9fd45d354e91696991d9a53c.png


后来终于知道原来这些效果需要自己去实现底层的着色器代码,去对每个像素做自己想要的控制。所以从去年开始,学习shader的计划就在自己心中开始了发芽,但是因为去年挺忙的,所以一直没有实践,今年上半年因为项目原因学习了一段时间的unity shaderlib,总算对shader有那么一点概念了。虽然后面unity没用上,但是自己终于可以慢慢转变到webgl的学习了。后续会在此专辑中持续记录webgl的学习过程,在此有几个前置条件需要声明一下

  • 如果你完全没有3D基础,那么不建议你看本内容,建议先从threejs入门了解基础的概念,它有很好的封装和抽象化,比起原生底层更容易理解,也更容易产生满足感,同时官网网站也非常人性化。
  • 本系列重点以shader学习为主,所示例的代码均以threejs的框架实现,不是完全以webgl来实现,原因有2点,1是原生webgl绑定过程和传递内容过程太过繁琐,2是因为threejs提供很多模型导入loader,可以更好地专注在shader代码实现上

最后列一下自己看的一些资料

书籍

  • 《Fundamentals of Computer Graphics, Fourth Edition》 老虎书,最经典的图形学入门

    7473d112c6b72aecf6116bdde4c53375.png
    Fundamentals of Computer Graphics, Fourth Edition - Matt Blatt
  • 《webgl编程指南》

  • 《3D数学基础(第二版)》

视频

  • 现代计算机图形学入门:https://www.bilibili.com/video/BV1X7411F744

图形学数学基础

在正式学习shader之前,我们需要先来了解一些基础的数学知识和概念,这会有助于我们后续知道为什么要这么计算。

向量

图形学中最重要的一个概念就是向量了。向量几乎参与了我们所有shader的计算,向量同时具有方向和大小,指的是从原点到一个点的指向。

大家应该还记得,他的表示方法为:

比如 和 其实是表示同一个方向的向量,但是模长不同

向量的模其实就是他的长度,使用勾股定理即可求出,一般我们把模长为1的向量称之为单位向量。

上面我们表示的是二维空间下的向量,如果延伸到三维空间,就是继续添加一个Z轴的分量,这个大家应该都能理解

那么向量有什么运算规则呢?

  • 加法(满足结合律和交换律)
  • 标量乘以向量(满足结合律和分配率)
  • 点乘,也称之为内积,结果为标量,一般用来求2个向量的夹角
  • 叉乘,也称之为外积,结果为向量,垂直于原向量构建的平面,可以根据2个向量构成的平面,求出垂直于这个平面的向量

向量的点乘

点乘的结果是一个标量

点乘公式有两种常见形式:

312f83e4694b7b9d5738df4769be403b.png

第一个是他的图形学意义,表示A向量在B上的投影长度,第二个是他的数学计算公式,通过上面2个公式,我们可以方便的根据向量求出2个向量之间的夹角。

它的实际用途一般用来判断2个向量的夹角是锐角还是钝角等

0d712fda256698eea11ef12d9734328c.png

向量的叉乘

向量的叉乘的结果是一个方向垂直于AB向量构成的平面的一个向量。如果AB两个向量是平行的,那么它们的叉乘就是一个零向量。

叉乘一般用来计算法向量,有一个很好用的判断就是右手定则,比如A.cross(B),将4指弯曲的方向由A->B。那么大拇指的方向就是最终结果的向量方向,也就是这个平面的法线方向。

f0089b96d9e1b8ed93a35f9fb5ad85ff.png

另外还有一个用途是判断一个点是否在封闭三角形内,如下图

ebe54aa3adf97e1fb3b8a71fec511a5f.png

我们可以使用.cross(),计算出一个向量,然后同理计算.cross() 和.cross(),如果这3个向量计算出来都是朝同一个方向,那么就可以判断P在ABC构成的封闭区间内。

一般来讲这些计算公式在unity / threejs中都已经有了封装,我们只需要传入2个向量即可,不需要自己去写数学公式,但是了解一下其作用和原理还是很有必要的。

矩阵

在图形学中另一个用到比较多的就是矩阵的计算了,因为会涉及到模型矩阵 -> 世界矩阵 -> 观察矩阵 ->投影矩阵等一系列的变化

矩阵的计算很简单,唯一需要注意一点的就是一个M行N列的矩阵只能和N行P列的矩阵相乘,结果是一个M行P列的矩阵

75e4e299f11041a912247859ac37b208.png

矩阵的作用

那么矩阵在图形学中为什么重要呢,因为图形学中物体的移动变换其实归纳起来就是缩放/平移/ 拉伸/旋转

这4个都可以通过矩阵方程式来表示,接下来参考虎书中的图例分别讲解一下

缩放矩阵

缩放变换是一种沿着坐标轴作用的变换,其表达式为

225d969747cc096b8f9fd8c9565fb6f5.png

e4a17031c2d1d7b97b612714e8c4bada.png

剪切矩阵(shearing)

shear变换直观理解就是把物体一边固定,然后去拖拽另一边,就好比把一个长方形拉成一个平行四边形

9de9ad633a9771928d8975810138e4c1.png

旋转矩阵

d77f2f9df83e1d5a81b5d46d073b3261.png

平移矩阵

平移其实相对以上几个来讲比较特殊,虽然他是最简单的变化,比如我们将一个坐标(1,2)向X轴平移2个单位其实就是(1+2,2) = (3,2),这个咋看之下好像没法用矩阵来表示,但是人们为了偷懒,想着既然其他的都能用矩阵表示,那么平移究竟怎么弄才能也用矩阵表示呢?后来人们就提出了一个概念,叫做齐次坐标。

齐次坐标

齐次坐标是在原有N维空间基础上再引入了一个维度,这样不仅解决了平移变换的矩阵需求,也解决了坐标和向量分不清的问题。

比如在二维坐标系下,(1,2)既可以表示x轴为1,Y轴为2的那个点,也可以表示 这个向量,那么到底怎么区分呢,人们就定义如果是(1,2,0)就表示 这个向量,如果是(1,2,1)就表示(1,2)这个点。同理在三维坐标系下就引入第4个量。

那为什么点和向量最后一个分量一个是1,而另一个是0呢?我们来看以下几个思考:

  • vector + vector = vector (第三维仍然是0,所以表示向量)
  • point - point = vector (这符合我们学习向量时所给出的定义,即某点指向另一个点,刚好表示向量,而且相减之后第三维恰巧就是0)
  • point + vector = point (这个好理解)
  • point + point = 什么呢?答案是2个点的中点,我们相加以后因为最后1个分量为2了,所以我们整体除以2,得到的最后一个分量为1,前面的点刚好是2个点连线的中点~

那么它又是怎么解决平移变换呢,答案如下图所示

c8034dede63acce1b7125fd375e57962.png

以上关于矩阵的推导过程可以参考:https://www.bilibili.com/video/BV1X7411F744,其中有明确的推导过程,这里不再赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值