ThreeJS掘金最通俗入门指南-城市地图构建案例

4,481 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

官方案例链接:three.js examples (threejs.org)

效果预览

image.png

步骤拆分

  1. 定义构建场景所需要的变量
  2. 初始化场景,设置场景背景色和场景中出现的雾的颜色
  3. 初始化关照,设置各个角度照射过来的平行光和物体本身会反射出来的环境光的颜色
  4. 初始化渲染器,定义渲染器为WebGL渲染器,设置他的大小和像素尺寸之后丢到文档的body下面去
  5. 初始化相机,定义相机的类型为透视相机,视野角度为60度,视野宽高比为屏幕的宽度比上高度,设置近视距离和最远观测距离
  6. 初始化轨道控制器,设置轨道控制器为地图轨道控制器,并定义他的最近观测距离和最远观测距离。设置轨道控制器移动的过程中是否会有阻尼惯性,如果有的话,惯性会有多大?
  7. 渲染模型,由于我们的模型会反射关照,所以这里我们选择使用 MeshPhongMaterial
  8. 渲染场景到页面上去

构建代码模板

<!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">
    <title>Document</title>
</head>

<body>
    <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

    <script type="importmap">
			{
				"imports": {
					"three": "../build/three.module.js"
				}
			}
	</script>
    <script type="module">

    </script>
</body>

</html>

导入依赖

import * as THREE from 'three';
import { MapControls } from './jsm/controls/OrbitControls.js';

定义变量&执行方法

let camera, controls, scene, renderer;
init();
animate();
function init(){
}
function animate(){
}

初始化场景

scene = new THREE.Scene();
scene.background = new THREE.Color( 0xcccccc );
scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );

初始化渲染器

renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

初始化相机

camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(400, 200, 0);

初始化地图轨道控制器

controls = new MapControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 100;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;

加载建筑

const geometry = new THREE.BoxGeometry( 1, 1, 1 );
geometry.translate( 0, 0.5, 0 );
const material = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } );
for ( let i = 0; i < 500; i ++ ) {
	const mesh = new THREE.Mesh( geometry, material );
	mesh.position.x = Math.random() * 1600 - 800;
	mesh.position.y = 0;
	mesh.position.z = Math.random() * 1600 - 800;
	mesh.scale.x = 20;
	mesh.scale.y = Math.random() * 80 + 10;
	mesh.scale.z = 20;
	mesh.updateMatrix();
	mesh.matrixAutoUpdate = false;
	scene.add( mesh );
}

加载灯光

const dirLight1 = new THREE.DirectionalLight( 0xffffff );
dirLight1.position.set( 1, 1, 1 );
scene.add( dirLight1 );
const dirLight2 = new THREE.DirectionalLight( 0x002288 );
dirLight2.position.set( - 1, - 1, - 1 );
scene.add( dirLight2 );
const ambientLight = new THREE.AmbientLight( 0x222222 );
scene.add( ambientLight );

将场景渲染到页面上面去&执行操作动画

function animate() {
    requestAnimationFrame( animate );
    controls.update(); 
    render();
}
function render() {
    renderer.render( scene, camera );
}

思考这个场景中使用的ThreeJS API

以上我们这个案例就做完了,但是做完之后我们还需要总结我们使用到了哪些API,并且我们是怎么使用他们的。方便下次我们遇到差不多的场景的时候我们能够再脑子里面第一时间想出解决方案来

模型渲染部分

我们使用到了 MeshPhongMaterial来作为我们生成建筑的材质。这个材质最大的特点就是它可以反射光线并且计算光线投射下来的阴影。

我们使用到了 BoxGeometry来作为我们要实际渲染的几何体,这个类同时也是4边形的原始几何类,它通常使用构造函数所提供的“width”、“height”、“depth”参数来创建立方体或者不规则四边形。

  • 构造函数:他的构造函数传递6个参数,分别是长宽高以及长宽高的面上会分成多少个段的参数。

我们使用到了 Mesh这个网格来混合我们的材质和几何体。这个类表示基于以三角形为polygon mesh(多边形网格)的物体的类。 同时也作为其他类的基类,

  • 构造函数: 构造函数传递两个参数,一个是Geometry,一个是Material
  • 位置参数(position):通过mesh.position.x|y|z我们可以设置我们要渲染到页面上面去的材质的x,y,z轴位置。
  • 缩放参数(scale): 通过mesh.scale.x|y|z 我们可以设置mesh相对于x|y|z轴的缩放比例。
  • 更新图形矩阵(updateMatrix):这个方法是在我们改变了图形的缩放比率和大小之后,我们在页面上面要重新渲染图形矩阵。
  • 是否每一帧的位移都要重新渲染图形矩阵(matrixAutoUpdate):设置了这个参数之后,我们就可以控制轨道控制器移动的时候是否会更新每个模型的位置了。我们这里是不需要更新的。

轨道控制器部分

我们这里使用到了 MapControls来作为我们的轨道控制器,也就是地图轨道控制器,下面我们来介绍轨道控制器的参数

  • enableDamping:是否开启阻尼,也就是拖动相机的时候会出现一点的阻碍感
  • dampingFactor:设置阻尼参数,也就是这个阻碍感会有多强
  • screenSpacePanning:设置是否可以拖动模型
  • minDistance: 设置地图轨道控制器的最小缩放距离
  • maxDistance:最大缩放距离
  • maxPolarAngle: 最大旋转尺寸

灯光部分

我们使用了两种灯光,一种是无限延展的直射光(DirectionalLight),一种是照射到场景物体上他会发出的自然光,也叫做阴影光(AmbientLight)

  • DirectionalLight: 平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。
    • 构造函数:传递两个参数,设置光照的颜色和光照的强渡
  • AmbientLight :环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。
    • 构造函数:传递两个参数,设置光照的颜色和光照的强度

【ThreeJS掘金最通俗入门指南-城市地图构建案例】 到此结束,如果您觉得对您有帮助的话,可以点赞收藏一下哦。您的支持就是对我最大的鼓励,能让我得到更多的推送流量,帮助到更多的人,最后感谢您花费宝贵的时间认真的阅读这篇文章。如果说您有什么需要我改进的建议欢迎到评论区一起和我讨论❤❤❤