Three.js 浅尝:基础3D渲染(二)
博客前述内容链接:Three.js 浅尝:基础3D渲染(一)
引言
上回书说道…
承接着上一篇博客,我们手里头已经有了构建好的几何对象 cube,后续就该是依着 WebGL 的套路把几何对象给绘制出来。
Three.js 渲染
再一次回顾前文中所抛出的那个 Three.js 的例子:
const canvas = document.querySelector('#canvas');
const renderer = new THREE.WebGLRenderer({
canvas});
const camera = new THREE.PerspectiveCamera();
camera.position.z = 2;
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff});
const cube = new THREE.Mesh(geometry, material);
cube.rotation.x = 2;
cube.rotation.z = -1;
scene.add(cube);
renderer.render(scene, camera);
现在我们已经有了构建完毕的 cube,剩下的就是把 cube 放到 scene 里头去、添加一个 camera、通过 renderer 将 cube 渲染出来。(WebGL 的例子较长,这里就不再重复了,请参见上一篇博客内容)
Scene
Scene
类的声明相当简单:
/**
* Scenes allow you to set up what and where is to be rendered by three.js. This is where you place objects, lights and cameras.
*/
export class Scene extends Object3D {
constructor();
type: 'Scene';
/**
* A fog instance defining the type of fog that affects everything rendered in the scene. Default is null.
*/
fog: IFog | null;
/**
* If not null, it will force everything in the scene to be rendered with that material. Default is null.
*/
overrideMaterial: Material | null;
autoUpdate: boolean;
background: null | Color | Texture;
...balabala
}
作为 scene graph 的根节点,Scene
类同样继承自 Object3D
基类,提供 add
与 remove
方法,允许在其下的层级中添加需要渲染的物体(或者 camera、light)。Scene
所提供的更多的是根节点的存储功能,其新增的属性和方法较少,包含 fog
(影响该场景下所有物体渲染的雾)以及 overrideMaterial
(强制其中所有物体应用该材质渲染)等,其余的便是对 toJSON
等父类中通用方法的实现。
Camera
常见的 PerspectiveCamera
以及 OrthographicCamera
均继承自基类 Camera
,其定义如下所示:
/**
* Abstract base class for cameras. This class should always be inherited when you build a new camera.
*/
export class Camera extends Object3D {
/**
* This constructor sets following properties to the correct type: matrixWorldInverse, projectionMatrix and projectionMatrixInverse.
*/
constructor();
/**
* This is the inverse of matrixWorld. MatrixWorld contains the Matrix which has the world transform of the Camera.
*/
matrixWorldInverse: Matrix4;
/**
* This is the matrix which contains the projection.
*/
projectionMatrix: Matrix4;
/**
* This is the inverse of projectionMatrix.
*/
projectionMatrixInverse: Matrix4;
isCamera: true;
getWorldDirection( target: Vector3 ): Vector3;
updateMatrixWorld( force?: boolean ): void;
}
一如之前所提的,Camera
也同样继承自 Object3D
基类,这也就意味着 Camera
类也支持旋转、平移等操作,即包含了变换矩阵。该变换矩阵由 Object3D
类中的 matrixWorld
属性存储,也就是模型矩阵(Model Matrix)。除去模型矩阵,作为 camera 也必然需要提供投影矩阵(Projection Matrix),即 projectMatrix
属性。
在 Camera
基类的基础上,不同的 camera 为其添加了所需的属性,以程序中所使用的 PerspectiveCamera
为例:
export class PerspectiveCamera extends Camera {
/**
* @param fov Camera frustum vertical field of view. Default value is 50.
* @param aspect Camera frustum aspect ratio. Default value is 1.
* @param near Camera frustum near plane. Default value is 0.1.
* @param far Camera frustum far plane. Default value is 2000.
*/
constructor( fov?: number, aspect?: number, near?: number, far?: number );
type: 'PerspectiveCamera';
isPerspectiveCamera: true;
zoom: number;
/**
* Camera frustum vertical field of view, from bottom to top of view, in degrees.
*/
fov: number;
/**
* Camera frustum aspect ratio, window width divided by window height.
*/
aspect: number;
/**
* Camera frustum near plane.
*/
near: number;
/**
* Camera frustum far plane.
*/
far: number;
...balabala
}
如果读者对于透视相机较为熟悉的话,PerspectiveCamera
类所添加的这些个属性便很好理解了,分别为 field of view(fov
)、视锥长宽比(aspect
)、视锥近平面(near
)、视锥远平面(far
)。
Program & Shader
在介绍最核心的 WebGLRenderer
类之前,还有一些类需要我们关注。虽然承担了最为重要的 render
api,但是在 Three.js 的设计中 WebGLRenderer
并不大包大揽,其中 WebGLProgram
实例以及 WebGLShader
实例的管理就交给了 Three.js 中同名类(请注意区分 WebGL 与 Three.js 中的 WebGLProgram
类与 WebGLShader
类,后者是对前者的封装。后续如无特殊声明则指 Three.js 中的类)。
上一篇博客中给出了 WebGL 绘制 cube 的一个例子,其出于教学目的省略了一些初始化的步骤。例子首先会调用额外提供的 getWebGLContext
函数获取到 WebGL context,其中隐藏了创建并启用 WebGLProgram
实例的过程。
在简单的渲染应用中,单一的 WebGLProgram
或许已经足以满足需求,但是需要实现 Three.js 所提供的复杂功能,便要求多个 WebGLProgram
实例的存在,其中每个实例均关联着两个 WebGLShader
,分别为顶点着色器与片段着色器。
着色器的封装十分简单,只需要根据字符串创建 WebGL 的 WebGLShader
实例:
function WebGLShader