three.js学习系列(一)————从概念到构建一个3D场景

Three.js、webGL和Canvas区别

Three.js是基于原生WebGL封装的三维引擎。
WebGL是JavaScript和OpenGL ES2.0结合起来的JavaScript API,在任何兼容的Web浏览器中渲染高性能的交互式3D和2D图形,该API可以在canvas元素中使用,可以html5 Canvas提供硬件的3D加速渲染。
Canvas是HTML5新增新增的标签,通过js脚本来完成图形绘制。

Three搭建一个基本场景

首先需要引入three.js, 可以直接通过cdn或者npm包安装。

npm i three.js -D

一个场景需要最基本的三要素:
**场景(scene):**可以理解为一个容器,用于保存、跟踪所要渲染的物体和使用的光源。可以将其比作一间房间。
**摄像机(camera):**决定在场景中看到的东西,可以理解为眼睛。
**渲染器(renderer):**场景中需要描述的东西,可以把它当做是画笔。

首先我们要有创建一个场景,这样才能将我们要制作的东西放到这房间(容器)里。
const scene = new THREE.Scene()
接着我们需要一台摄像机,也就是眼睛,没有眼睛啥也看不到。
const camera = new THREE.PerspectiveCamera(45, window,innerWidth/window.innerHeight, 0.1, 1000)

PerspectiveCamera(fov, aspect, near, far)
fov: 摄像机的垂直视野角。相当你能看到的视野广角度。
aspect: 可以看到区域的宽高比。
near: 摄像机能看到的最近垂直距离。
far: 摄像机能看到的最远垂直距离。
这个可以看成是一个棱锥体。如下图眼睛看到角度是fov, 看到区域的狂高比是aspect.可以看到的范围是near->far(既棱锥体内的内容,其它地方都看不到的)
three.js学习系列(一)————从概念到构建一个3D场景_第1张图片
有了房间,有了眼睛,但是没内容看啊!

接着我们创建一个渲染器,也就是画笔。
// 创建一个渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染器的颜色
renderer.setClearColor(new THREE.Color(0x000000))
// 绘制的面积
renderer.setSize(window.innerWidth, window.innerHeight)

这里我们创建了一只画笔,调用setClearColor方法将场景背景色设为黑色,通过setSize设置了场景的大小,即可渲染区域。这时候我们已经创建了一个全黑的房间。
创建完这些最基本的还需要将该方法添加到页面中。最后还要调用渲染器把里面的东西给画出来才能在页面显示。代码如下。

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script type="text/javascript" charset="UTF-8" src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.js">script>
  <title>demotitle>
head>
<body>
  <div id="webgl-output">div>

  <script type="text/javascript">
	const scene = new THREE.Scene(); // 创建一个场景
  // 创建一台摄像机
	var camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
	// 创建一个渲染器
	const renderer = new THREE.WebGLRenderer();
	renderer.setClearColor(new THREE.Color(0x000000));
	renderer.setSize(window.innerWidth, window.innerHeight);
	// 将要显示内容挂在到html中
	document.getElementById("webgl-output").appendChild(renderer.domElement);
	// 渲染容器中内容
	renderer.render(scene, camera);
  script>
body>
html>

好了现在应该是什么也没看,只看到黑黑的房间,因为里面没内容。

创建一个平台和添加材质

three.js中有两个很常用的基类Geometry(几何结构)和Material(材质)
three.js中有两个很常用的基类Geometry(几何结构)和Material(材质)

// 创建一个宽60长20的平台几何体
const planeGeometry = new THREE.PlaneGeometry(60, 20);
// 采用颜色为0xAAAAAA的基本的材质
const planeMaterial = new THREE.MeshBasicMaterial({
    color: 0xAAAAAA
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);

我们创建了一个PlaneGeometry平台的几何图形,其材质颜色是0xAAAAAA。然后调用THREE.Mesh将其两则结合就是我们需要的平台。
(我们采用的是basic的材质,最常用的有三种材质,后序会介绍。)
接着我们还需要将其放到容器里,如果不设置默认放到坐标0,0,0的位置,即中心位置

//rotate and position the plane
// 旋转90度
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(15, 0, 0);
// 将平台添加到容器中
scene.add(plane);

我们将其旋转90度(不旋转其是很垂直的一个),然后设置其位置,(x,y,z)如下。z是距离屏幕的距离。
three.js学习系列(一)————从概念到构建一个3D场景_第2张图片
现在平台已经搭好了这时候,发现还是一片黑。这是因为我们摄像机的位置没放好,如果不设置摄像机的位置默认是(0,0,0)所以什么也看不到。

camera.position.set(-30, 40, 30);
camera.lookAt(scene.position);

这里设置了摄像机的位置position和lookAt,其就是看向位置,为场景的中心。(当然你可以调试不同的位置)。这时候我们应该是可以看到页面如下。
three.js学习系列(一)————从概念到构建一个3D场景_第3张图片
接下来我们创建一个正方体放到平台上。代码和上述创建平台类似就不再阐述了。

// create a cube
    const cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    const cubeMaterial = new THREE.MeshBasicMaterial({
        color: 0xFF0000,
        wireframe: true // 显示骨架
    });
    const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

    // position the cube
    cube.position.set(-4, 3, 0);

    // add the cube to the scene
    scene.add(cube);

添加到后的效果如下
three.js学习系列(一)————从概念到构建一个3D场景_第4张图片

添加材质、光源和阴影效果

这里补充介绍下three.js中三种常用材质
MeshBasicMaterial: 对光无感,给几何体一种简单的颜色和显示线框
**MeshLambertMaterial:**这种材质对光照有反应,用于创建暗淡不发光物体
**MeshPhongMaterial:**这种材质对光照有反应,用于创建金属类型明亮的物体

基本的材质是对光照无感,我们将上诉正方体由MeshBasicMaterial换成MeshLambertMaterial并去掉其骨架显示。

const  cubeMaterial = new THREE.MeshLambertMaterial({
   color: 0xFF000000
})

可以看到修改后的正方体是全黑的一片,这是因为我们还没有添加光源。

const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 20, -5);
spotLight.castShadow = true;
scene.add(spotLight);

这段代码很简单,添加了一光源设置了其位置,就可以看到正方体本来的颜色,不同光照颜色会结合物体的颜色呈现不同效果。在上面我们还设置了一个castShadow的属性,表示这个光源可以产生阴影效果。但是在效果上并没有看到。
因为three.js还需要指明渲染器能渲染阴影,哪个物体投影阴影和哪个对象才能才生阴影(材质可对光有反应的前提下)。所以我们还需要更改平台的材质才能投影阴影

const planeMaterial = new THREE.MeshLambertMaterial({
    color: 0xffffff
});
// 设置渲染器能才生阴影
renderer.shadowMap.enabled = true
cube.castShadow = true

效果如下
three.js学习系列(一)————从概念到构建一个3D场景_第5张图片

整体代码如下:

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script type="text/javascript" charset="UTF-8" src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.js">script>
  <title>demotitle>
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
  style>
head>
<body>
  
  <div id="webgl-output">div>

  
  <script type="text/javascript">
    // create a scene, that will hold all our elements such as objects, cameras and lights.
    const scene = new THREE.Scene();

    // create a camera, which defines where we're looking at.
    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    // create a render and set the size
    const renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(new THREE.Color(0x000000));
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true

    // create the ground plane
    const planeGeometry = new THREE.PlaneGeometry(60, 20);
    const planeMaterial = new THREE.MeshLambertMaterial({
        color: 0xffffff
    });
    const plane = new THREE.Mesh(planeGeometry, planeMaterial);

    // rotate and position the plane
    plane.rotation.x = -0.5 * Math.PI;
    plane.position.set(15, 0, 0);
    plane.receiveShadow = true

    // add the plane to the scene
    scene.add(plane);

    // create a cube
    const cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
    const cubeMaterial = new THREE.MeshLambertMaterial({
        color: 0xFF00000
    });
    const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

    // position the cube
    cube.position.set(-4, 3, 0);
    cube.castShadow = true

    // add the cube to the scene
    scene.add(cube);

    const spotLight = new THREE.SpotLight(0xffffff);
    spotLight.position.set(-10, 20, -5);
    spotLight.castShadow = true;
    scene.add(spotLight);

    // position and point the camera to the center of the scene
    camera.position.set(-30, 40, 30);
    camera.lookAt(scene.position);

    // add the output of the renderer to the html element
    document.getElementById("webgl-output").appendChild(renderer.domElement);

    // render the scene
    renderer.render(scene, camera);
  script>
body>
html>

当然如果想添加动画和操作效果可以利用js修改对象的position来实现。
这只是构建一个基本的场景,后续会继续详细分析其sence,材质,光源,动画等api可以直接参考官网,其用法基本大同小异。

你可能感兴趣的:(three.js)