简单搬运和记录一下入门 three.js 之前做的一些准备好了,毕竟前后花了几天时间在熟悉这部分内容,包括图形学的一些基础概念。尽管使用 three.js 开发的时候这部分内容对于开发者又几乎是透明的,都是概念的东西_(:з」∠)_

齐次坐标

齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换

齐次坐标采用 N+1 个量来表示 N 维坐标,例如将一个二维点(x,y)表示为(X,Y,w),三维点(x,y,z)表示为(X,Y,Z,w)。有如下两个优点:

1. 区分向量和点

在坐标系xOy中,用(a,b)定义一个向量 \(\vec v\) 时,表示 \(\vec v = a\vec x + b\vec y\);用(a,b)定义一个点 p 时,表示 \(p - o = a\vec x + b\vec y\)。这种情况下,无法区分向量和点,而引入齐次坐标则很好地解决了这个问题

类型 普通表示 齐次坐标表示
向量 \(\vec v\) \(\vec v = a\vec x + b\vec y\) \( p = {\begin{bmatrix} a & b & 0 \end{bmatrix}} {\begin{bmatrix} \vec x \\ \vec y \\ o \end{bmatrix}} \)
点 p \(p - o = a\vec x + b\vec y\) \( p = {\begin{bmatrix} a & b & 1 \end{bmatrix}} {\begin{bmatrix} \vec x \\ \vec y \\ o \end{bmatrix}} \)

2. 易于进行几何变换

之所以说齐次坐标能易于几何变换,是因为它能把线性变换和平移变换的运算用矩阵相乘的形式来计算。此外,模型矩阵的使用也降低了重复计算量。

类型 普通表示 齐次坐标表示
缩放变换 \({\begin{bmatrix} x̀ \\ ỳ \end{bmatrix}} = {\begin{bmatrix} S_x & 0 \\ 0 & S_y \end{bmatrix}} {\begin{bmatrix} x \\ y \end{bmatrix}}\) \({\begin{bmatrix} x̀ \\ ỳ \\ 1 \end{bmatrix}} = {\begin{bmatrix} S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1\end{bmatrix}} {\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}}\)
平移变换 \({\begin{bmatrix} x̀ \\ ỳ \end{bmatrix}} = {\begin{bmatrix} t_x \\ t_y \end{bmatrix}} + {\begin{bmatrix} x \\ y \end{bmatrix}}\) \({\begin{bmatrix} x̀ \\ ỳ \\ 1 \end{bmatrix}} = {\begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix}}{\begin{bmatrix} x \\ y \\ 1 \end{bmatrix}} \)

矩阵

大学上高数肯定有接触到矩阵啦,这里要提的是下面几个概念。

模型矩阵

将最初的点坐标左乘这个矩阵就能得到一系列变换后最终的点坐标,这个矩阵称为“模型矩阵”

视图矩阵

将世界里的所有模型看作一个大模型,在所有模型矩阵的左侧再乘以一个表示整个世界变换的模型矩阵,这个表示整个世界变换的矩阵又称为“视图矩阵”

模型视图矩阵

视图矩阵乘以模型矩阵得到的矩阵称为“模型视图矩阵”

投影

不得不佩服一叶斋这几篇文章的介绍,我就不搬运了

正射投影

正射投影

透视投影

透视投影

Shaders and GLSL

Shader

Shader 即着色器。每次通过 WebGL 绘制一个物体的时候,都会需要两个着色器,顶点着色器和片元着色器。每一个着色器是一个函数,一个着色程序则同时包括了顶点着色器和片元着色器,而一个 WebGL 渲染出来的场景通常需要多个着色程序。更为具体的介绍请务必戳这里或者这里,对我帮助很大。

着色器

Vertex Shader (顶点着色器)

主要处理每个顶点的坐标信息

<script type="x-shader/x-vertex" id="vertex-shader">
attribute float size;
uniform vec3 color;
varying vec4 vColor;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
float alpha = 1.0;
vColor = vec4(color, alpha);
gl_Position = projectionMatrix * mvPosition;
gl_PointSize = size;
}
</script>

可以看到除了数据类型 float, vec3,变量前面的 attribute, uniform 则表示变量是如何传递到着色器。

类型 作用
attribute 由缓冲区输入数据
uniform 在所有顶点处理过程中保持一致
varying 从顶点着色器经过光栅化后传递给片元着色器

Fragment Shader (片元着色器)

提供每一个像素的颜色信息

<script type="x-shader/x-fragment" id="fragment-shader">
uniform sampler2D texture;
varying vec4 vColor;
void main() {
gl_FragColor = vColor * texture2D(texture, gl_PointCoord);
}
</script>
类型 作用
uniform 在所有像素处理过程中保持一致的值
varying 从顶点着色器经过光栅化后传递到片元着色器

参考资料

内容也差不多是这些了,下面才是干货…

http://webglfundamentals.org/
http://www.cnblogs.com/yiyezhai/category/446753.html
http://wiki.jikexueyuan.com/project/webgl/
https://oncemore2020.github.io/blog/homogeneous/
http://csgrandeur.github.io/
http://threejs.org/