• 【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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 通过 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 之后我们可以看到一个灰色的画布

    Ⅲ. 创建坐标系

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

    在这里插入图片描述

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

    • 平面的创建,需要大小(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); // 将地面添加到坐标轴中
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 立方体的创建 (同理)
    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 球的创建 ( 同理 )
    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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

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

    Ⅴ. 光源的创建

    • 创建灯光的类型,和颜色;
    • 设置光源的位置;
    • 设置光源,投影的长度;
    • 同理用 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

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

    Ⅵ.添加投影

    • 要投影的元素设置 castShadow 设置为 true;
    • 被投影的元素设置 receiveShadow 设置为 true;
    • 同理添加到 appendChild 插入前;
    • 该场景 地面为要投影的位置,球和立方体为被投影物体 ↓
    plane.receiveShadow = true;   //地面被投影
    
    sphere.castShadow = true;  //球投影
    cube.castShadow = true;    //立方体投影
    point.castShadow = true;   //灯光投影
    
    renderer.shadowMap.enabled=true;  //让渲染器支持投影
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 低版本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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 然后就属性这个小案例了

    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

      
    <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>Documenttitle>
    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 每周更新2篇 - 下一节 threeJS 实现 3d魔方

    在这里插入图片描述

  • 相关阅读:
    Redis面试题:redis做为缓存,数据的持久化是怎么做的?两种持久化方式有什么区别呢?这两种方式,哪种恢复的比较快呢?
    车载电子电器架构 —— 车辆模式管理
    深入浅出Dart》函数
    python3-- Pillow10 ‘FreeTypeFont‘ object has no attribute ‘getsize‘报错解决
    Django中的缓存
    实现响应式网页设计
    [刷题记录]牛客面试笔刷TOP101(二)
    深入探析:云计算与边缘计算在软件开发中的应用与挑战
    软件面试逻辑题
    CAS号:1937270-46-6|PC Biotin-PEG3-azide|PC生物素-PEG3-叠氮化物
  • 原文地址:https://blog.csdn.net/weixin_42232622/article/details/126214013