创建一个Threejs案例,必不可少的要素有场景、相机、渲染器、光源。

基本步骤

1、性能监听 initStats();

var  stats = initStats();

2、创建场景Scene

var  scene = new THREE.Scene();

3、创建相机,透视投影相机 PerspectiveCamera

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

第一个参数是可视角度,第二个参数是实际窗口的纵横比,第三个参数是近处裁面距离,第四个参数是远处裁面距离。

4、创建渲染器,WebGLRenderer,使用WebGL绘制场景,利用GPU硬件加速提高渲染性能,渲染器背景色、范围大小、是否显示阴影的设置。

var renderer = new THREE.WebGLRenderer();

renderer.setClearColor(new THREE.Color(0x000000)); //背景色

renderer.setSize(window.innerWidth, window.innerHeight);

renderer.shadowMap.enabled = true;  // 显示阴影

6、创建一个平面,包括几何体、材质,把几何体、材质添加到网格中,同时设置平面接受阴影。

var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);

var planeMaterial = new THREE.MeshLambertMaterial({ color:  0xffffff });

var plane = new THREE.Mesh(planeGeometry, planeMaterial);

plane.receiveShadow = true;

7、平面位置设置

plane.rotation.x = -0.5 * Math.PI;

plane.position.x = 15;

plane.position.y = 0;

plane.position.z = 0;

8、把平面添加到场景中

scene.add(plane);

9、设置相机的位置,并把镜头指向场景中心

camera.position.x = -30;

camera.position.y = 40;

camera.position.z = 30;

camera.lookAt(scene.position);

10、设置环境光、聚光,并添加到场景中

var ambientLight = new THREE.AmbientLight(0x353535);    // 环境光

scene.add(ambientLight);

var spotLight = new THREE.SpotLight(0xffffff);  // 聚光

spotLight.position.set(-10, 20, -5);

spotLight.castShadow = true;

scene.add(spotLight);

11、把渲染器挂载到页面上,场景、相机作为参数传给render。

document.getElementById("webgl-output").appendChild(renderer.domElement);

renderer.render(scene, camera);

至此,一个渲染器渲染出了一个带有一个平面、环境光、聚光的场景。以上也是一般建立一个Three.js场景并渲染出来的基本过程。

image.png

把物体添加到场景中

现在还要做的是在场景中添加两个物体,立方体和球体。物体需要在相机定位之前添加到场景中。

// 创建立方体
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);      // 几何体
var cubeMaterial = new THREE.MeshLambertMaterial({ color:  0xff0000 });     // 材质

var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);   // 网格

cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;

cube.castShadow = true;

// 添加立方体到场景中
scene.add(cube);
// 创建球体
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({ color:  0x7777ff });

var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

sphere.position.x = 20;
sphere.position.y = 0;
sphere.position.z = 2;

sphere.castShadow = true;

// 添加球体到场景中
scene.add(sphere);

至此,能够在平面上看到两个带有阴影的静止的物体。
image.png

让物体动起来

如果需要把物体做一个动画处理,需要使用到requestAnimationFrame(render)这个函数,参数也是一个函数,这个参数函数用来对物体的旋转、物体位置进行设置。把requestAnimationFrame(render)这个函数放到参数函数render里面调用,实现动画效果。另外还要把之前写过的renderer.render(scene, camera);这个渲染语句剪切放到里面。

具体实现。

function render () {
    stats.update();
    
    // 立方体能同时围绕x、y、z轴旋转
    cube.rotation.x += 0.02;
    cube.rotation.y += 0.02;
    cube.rotation.z += 0.02;
    
    step += 0.04;
    
    // 球体在x轴方向来回移动,同时在y轴方向做曲线运动
    sphere.position.x = 20 + (10 * (Math.cos(step)));
    sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));

    requestAnimationFrame(render);

    renderer.render(scene, camera);
}

threejs1.gif

控制物体改变的速度

如图中所示,物体能够按照一定的幅度自动进行旋转、跳动,如果想要控制物体的旋转、跳动幅度,可以使用threejs库中的控件。具体可以这样做。

在第11步骤的后面,紧接着写上

var step = 0;

var controls = new function () {
    this.rotationSpeed = 0.02;
    this.bouncingSpeed = 0.03;
};

var gui = new dat.GUI();
gui.add(controls, 'rotationSpeed', 0, 0.5);
gui.add(controls, 'bouncingSpeed', 0, 0.5);

var trackballControls = initTrackballControls(camera, renderer);

var clock = new THREE.Clock();

render函数里的内容,调整如下

function render () {
    trackballControls.update(clock.getDelta());

    stats.update();

    cube.rotation.x += controls.rotationSpeed;
    cube.rotation.y += controls.rotationSpeed;
    cube.rotation.z += controls.rotationSpeed;

    step += controls.bouncingSpeed;
    sphere.position.x = 20 + (10 * (Math.cos(step)));
    sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));

    requestAnimationFrame(render);

    renderer.render(scene, camera);
}

render();

在浏览器中,调控右上角的控件,可以改变球体的跳动速度或者立方体的旋转速度。
threejs3.gif

添加坐标轴

如果想要查看坐标轴,可以把坐标轴添加到场景中。

var  axesHelper = new THREE.AxesHelper( 150 );
scene.add( axesHelper );

坐标轴如下,红色为x轴,绿色为y轴,蓝色为z轴。
xyz <====> rgb

threejs4.gif

即时监听窗口变化即时渲染窗口大小

如果改变窗口大小,会发现渲染器的渲染有点问题,比如缩小页面又放大页面之后,没能及时监听到窗口大小的变化,从而渲染不全整个页面。

解决方法是写一个监听函数。

function onResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    
    camera.updateProjectionMatrix();
    
    renderer.setSize(window.innerWidth, window.innerHeight);

}

然后在最开始,进行监听。

window.addEventListener('resize', onResize, false);

// 接着的是性能监听...
// ...

参考

Three.js开发指南:基于WebGL和HTML5在网页上渲染3D图形和动画(原书第3版), (美)乔斯·德克森


JJYin
3 声望1 粉丝