【WebGL 3D前沿】threeJs 入门篇

1.什么是threeJs

  • 简单的说 ,就是一门 绘制 3DjavaScript 轻量级框架;
  • 主要采用 ,HTML5 Canvas提供硬件3D加速渲染;
  • 于是web 端 ,就能制作出 3D 系统 ,访问就能操作 ,十分方便。

Ⅰ.为什么要学这门前沿技术

  • threeJs 是前端3D框架中最突出的一个;请添加图片描述

  • 优点:WebGL 前端工程师的工资,相比较于做vue,react 项目开发的工资普遍要的多,竞争较少

  • 缺点:threeJs资源匮乏文档粗糙 ,three要有一定的数学基础.

Ⅱ.应用场景

  • 引用场景十分之多,未来会更多。
  • 游戏,地图,智能工厂,智慧园区,360°模型 ,建筑家装,3d物联网 …
  • 应用场景是十分之多, 目前 threeJs 学习的人并不多 , 所以threeJs 的工资普遍较高。

2. 学习Three .js 入门篇 (一)

下面 以下例子 入门第一篇 :
在这里插入图片描述

Ⅰ.安装下载

  • 官方包比较大,建议单独下载该文件(存在大量实例) => https://github.com/mrdoob/three.js/blob/dev/build/three.js
  • 初始化准备 ↓
<script src="./build/three.js"></script>
<style>
    body {
     
     
        margin: 0;
        overflow: hidden;
    }
</style>

<body>
    <div id="threeBox"></div>    
</body>
<script>
        function init() {
     
      /* 页面加载完成开始渲染Three内容 */}
        window.onload = init;
</script>
  • 通过 window.onload 页面加载完成,开始操作 three 实例、

Ⅱ. 创建场景、摄像机、渲染器(画布)

  • 场景(scene) :用于把创建完成的模型 添加到 画布中。
  • 摄像机 (camera): 相当于人眼所在的位置 ;
  • 渲染器(renderer):相当于canvas 画布元素。
  • 创建三个元素 ,然后把画布 插入到html 元素中 ↓
function init() {
    
    
	// 创建场景
	let scene = new THREE.Scene();


	// 创建摄像机
	let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000); // (角度  , 长款比  , 最近看到的距离, 最远)
 	camera.position.x = -30;
    camera.position.y = 40;
    camera.position.z = 30;
    camera.lookAt(scene.position); //将相机指向场景


	//创建渲染器 (画布)
	let renderer = new THREE.WebGLRenderer();
	renderer.setClearColor(0xeeeeee); //canvas画布颜色
	renderer.setSize(window.innerWidth, window.innerHeight);  //canvas 画布大小	
	
	
	// 将这个canvas元素插入到 html中
	document.getElementById('threeBox').appendChild(renderer.domElement);
    renderer.render(scene, camera);	
}
window.onload = init;
  • 之后我们可以看到一个灰色的画布

Ⅲ. 创建坐标系

  • 以便更好的确定其他元素的位置
  • 用scene.add 去添加元素到画布;
  • 必须在appendChild 插入前 ↓
     let axes = new THREE.AxesHelper(30); //坐标系的长度
     scene.add(axes); //坐标系添加到场景中

在这里插入图片描述

Ⅳ.平面、立方体、球 的创建

  • 平面的创建,需要大小(PlaneGeometry)和材质(MeshStandardMaterial) 两个对象;
  • 然后用 THREE.Mesh 去创建模型 (包括后面的 球 和 立方体)
  • 同样模型,创建完成后 scene.add 添加到画布中

let planeGeometry = new THREE.PlaneGeometry(60, 20); // 创建地面的大小
let planeMaterial = new THREE.MeshStandardMaterial({
    
     color: 0x999999 }); //地面的材质
let plane = new THREE.Mesh(planeGeometry, planeMaterial); // 创建地面
plane.rotation.x = -0.5 * Math.PI;  // 旋转角度
plane.position.x = 15;  // 设置地面 xyz 轴的位置
plane.position.y = 0;
plane.position.z = 0;  
scene.add(plane); // 将地面添加到坐标轴中
  • 立方体的创建 (同理)
let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);  //长宽高
let cubeMaterial = new THREE.MeshLambertMaterial({
    
     color: 0xff0000 });  //材质颜色
let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = 3;  //三轴的位置
cube.position.y = 8;
cube.position.z = 3;
scene.add(cube);
  • 球的创建 ( 同理 )
let sphereGeometry = new THREE.SphereGeometry(2,20,20); //半径,圆滑程度
let sphereMaterial = new THREE.MeshLambertMaterial({
    
     color: 'blue' }); //材质颜色
let sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x = 24; //三轴的位置
sphere.position.y = 4;
sphere.position.z = 4;
scene.add(sphere);

在这里插入图片描述

  • 此时我们可以看到,地面,立方体,和球,都没有颜色 , 说明我们没有光源 ,下面我们要添加光源。

Ⅴ. 光源的创建

  • 创建灯光的类型,和颜色;
  • 设置光源的位置;
  • 设置光源,投影的长度;
  • 同理用 scene.add 去添加到 canvas画布。
// 添加聚光灯
let point = new THREE.SpotLight(0xffffff);  //设置灯光的颜色
point.position.set(80, 100, 80); //点光源位置
point.angle = Math.PI/10;  //设置投影的程度
point.shadow.mapSize.set(1024,1024);
scene.add(point)

在这里插入图片描述

  • 我们发现此时 并没有投影。

Ⅵ.添加投影

  • 要投影的元素设置 castShadow 设置为 true;
  • 被投影的元素设置 receiveShadow 设置为 true;
  • 同理添加到 appendChild 插入前;
  • 该场景 地面为要投影的位置,球和立方体为被投影物体 ↓
plane.receiveShadow = true;   //地面被投影

sphere.castShadow = true;  //球投影
cube.castShadow = true;    //立方体投影
point.castShadow = true;   //灯光投影

renderer.shadowMap.enabled=true;  //让渲染器支持投影
  • 低版本threeJs 让渲染器支持投影 => renderer.shadowMapEnabled = true
    在这里插入图片描述
  • 最后就差 鼠标的拖到旋转,和滚轮的缩放

Ⅶ.鼠标操控三维场景

  • 鼠标操控三维场景 需要再添加一个threeJs 的三方插件

下载地址: https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js

  • 在appendChild 插入后 添加
  • 监听鼠标的事件 ,一但发生 重新调用 rander() 方法
<script type="text/javascript" src="../threeJs/three.js"></script>
<script src="../threeJs/OrbitControls.js"></script>
 
 
...
<script>
function init() {
    
    
    // ... 在appendChlid 后面添加
	let controls = new THREE.OrbitControls(camera,renderer.domElement);
    controls.addEventListener('change',()=>{
    
    
    	renderer.render(scene, camera);
	});
}
window.onload = init;
</script>
  • 然后就属性这个小案例了

3. 整合代码

  • 这个threeJs 包太大,包括许多案例,建议直接下载这两个文件。

threeJs => https://github.com/mrdoob/three.js/blob/dev/build/three.js
OrbitControls.js => https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js

  <!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>
<script  src="../threeJs/three.js"></script>
<script src="../threeJs/OrbitControls.js"></script>
<style>
    body {
     
     
        margin: 0;
        overflow: hidden;
    }
</style>

<body>
    <div id="threeBox"></div>
    <script>
        function init() {
     
     
            // 创建场景
            let scene = new THREE.Scene();


            // 创建摄像机
            let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
            //定位相机
            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position); //将相机指向场景


            //创建渲染器 (画布)
            var renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(0xeeeeee); //渲染初始颜色
            renderer.setSize(window.innerWidth, window.innerHeight);  //canvas 画面大小
            //渲染设置 3d 投影
            renderer.shadowMap.enabled=true;


            //显示三维坐标
            let axes = new THREE.AxesHelper(20); //坐标系的长度
            scene.add(axes); //坐标系添加到场景中


            // 创建地面的大小
            let planeGeometry = new THREE.PlaneGeometry(60, 20); //地面的宽高
            //地面上色
            let planeMaterial = new THREE.MeshStandardMaterial({
     
      color: 0x999999 });
            // 创建地面
            let plane = new THREE.Mesh(planeGeometry, planeMaterial);
            // 设置地面的位置
            plane.rotation.x = -0.5 * Math.PI;
            plane.position.x = 15;
            plane.position.y = 0;
            plane.position.z = 0;  
            // //将地面添加到坐标轴中
            scene.add(plane);
            plane.receiveShadow = true;
          

            // //添加正方形
            let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            let cubeMaterial = new THREE.MeshLambertMaterial({
     
      color: 0xff0000 });
            let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.position.x = 3;
            cube.position.y = 8;
            cube.position.z = 3;
            scene.add(cube);
            cube.castShadow = true;


            //添加球
            let sphereGeometry = new THREE.SphereGeometry(2,20,20);
            let sphereMaterial = new THREE.MeshLambertMaterial({
     
      color: 'blue' });
            let sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);
            sphere.position.x = 24;
            sphere.position.y = 4;
            sphere.position.z = 4;
            sphere.castShadow = true;
            scene.add(sphere);


            // 添加聚光灯
            var point = new THREE.SpotLight(0xffffff);
            point.position.set(80, 100, 80); //点光源位置
             // 通过add方法插入场景中,不插入的话,渲染的时候不会获取光源的信息进行光照计算
            point.angle = Math.PI/10;
            point.shadow.mapSize.set(1024,1024)  
            scene.add(point)
            point.castShadow = true;


            document.getElementById('threeBox').appendChild(renderer.domElement);
            renderer.render(scene, camera);


            let controls = new THREE.OrbitControls(camera,renderer.domElement);
            controls.addEventListener('change',()=>{
     
     
                renderer.render(scene, camera);
            });
        }
        window.onload = init;
    </script>
</body>
</html>
  • 每周更新2篇 - 下一节 threeJS 实现 3d魔方

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42232622/article/details/126214013