• Three入门学习笔记整理


    Three入门学习笔记整理


    一、官方网站:https://threejs.org

    二、关于Three.js

    WebGL是大部分浏览器直接支持的一种3D绘图标准,它可以创建二维图形和应用,还可以充分利用GPU,创建漂亮的、高性能的三维应用。直接使用WebGL非常复杂,Three.js库提供了一套基于WebGL的、非常易用的JavaScrip API,它源自github的一个开源项目,通过这些API可以直接在浏览器中创建三维场景。本文整理了一些入门资料。

    三、开始

    • 引入
      可以直接在HTML引入Three.js
    <script src="three.js"></script>  
    

    也可以用npm安装:
    npm i three
    import * as THREE from 'three'

    • 使用
      three渲染一个3D场景需要以下必要元素:
      1.场景(Scene):是物体、光源等元素的容器,要渲染的东西需要先添加进场景;
      2.相机(Camera):控制视角的位置、范围以及视觉焦点的位置,一个3D环境中只能存在一个相机;
      3.光源(Light):包括全局光、平行光、点光源;
      4.物体对象(Mesh):包括二维物体(点、线、面)、三维物体、粒子等;
      5.渲染器(Renderer):指定渲染方式,如webGLcanvas2DCss2DCss3D等;
      非必要元素
      控制器(Control):相机控件,可通过键盘、鼠标控制相机的移动。

    四、实例

    基本结构

    const width = window.innerWidth;  
    const height = window.innerHeight;   
    var renderer;  
    var camera;  
    var light;  
    var scene;   
    
    function initRender() {
      // 初始化渲染器
      renderer = new THREE.WebGLRenderer({
        antialias: true// 抗锯齿
      });
      renderer.setSize(width, height);  // 设置大小
      renderer.setClearColor(0xffffff, 1.0);  // 设置背景色
      document.body.appendChild(renderer.domElement);  
    }
    
    function initScene() {  
      // 初始化场景
      scene = new THREE.Scene();  
    }
    
    function initCamera() {  
      // 初始化相机
      camera = new THREE.PerspectiveCamera(45, width / height, 10, 10000);  // 添加透视相机
      camera.position.set(500, 500, 500); // 设置相机位置  
      camera.up.set(0, 1, 0);  // 相机以哪个轴为上方
      camera.lookAt(0, 0, 0);  // 相机焦点设置
    }
    
    function initLight() {  
      // 初始化灯光
      light = new THREE.DirectionalLight({ color: 0xffffff });  // 添加平行光
      light.position.set(1, 0, 0); // 光的方向(x,y,z) 
      scene.add(light);  
      let pointLight = new THREE.PointLight(0xffffff);  // 添加点光源  
      pointLight.position.set(100, 100, 100);  // 点光源的位置
      scene.add(pointLight);  
      let pointHelper = new THREE.PointLightHelper(pointLight, 5, 0xff0000);  // 设置点光源辅助工具,可以看到点光源的位置  
      scene.add(pointHelper);
    }
    
    function initObject() {  
      // 初始化物体
      let geometry = new THREE.CylinderGeometry(100, 100, 300, 100, 100); // 添加一个圆柱体
      let material = new THREE.MeshLambertMaterial({
    	color: 0xffff00
      }); // 添加材料
      // material.wireframe=true; // 圆柱体是否以网格显示
      mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(0, 0, 0);
      scene.add(mesh);
    }
    
    function initAxes() {
    // 添加辅助坐标轴
      let axes = new THREE.AxesHelper(1000);// 蓝色为Z轴,绿色为Y轴,红色为X轴
      scene.add(axes);
    }
    
    function threeStart() {  
      initRender();  
      initScene();  
      initCamera();  
      initLight();  
      initAxes();  
      initObject();  
      renderer.clear();
      renderer.render(scene, camera);
    }
    
    window.onload = function () {  
      threeStart();  
    };  
    

    结果

    五、概念

    坐标系

    three.js中采用的是右手坐标系,坐标轴方向主要是camera.up.set(x, y, z);设置。也就是说在相机眼里(其实就是我们看的角度)哪个轴向上。理解坐标系很重要,详情请看three右手坐标系讲解

    场景

    物体、光源、控制器的添加必须使用secen.add(object)添加到场景中才能渲染出来。

    var scene;
    function initScene(){
      scene=new THREE.Scene();
    }
    

    相机

    正交投影相机
    THREE.OrthographicCamera(left, right, top, bottom, near, far) // 大小不因远近而变化
    透视投影相机
    THREE.PerspectiveCamera(fov, aspect, near, far) // 遵循近大远小的空间规则

    一般情况下,我们使用的是透视投影相机,其参数为:

    fov:垂直方向夹角(视角)
    aspect:可视区域长宽比 width/height
    near:渲染区域离摄像机最近的距离
    far:渲染区域离摄像机最远的距离,仅在距离摄像机near和far间的区域会被渲染到canvas中
    

    相机的位置设置:
    camera.position.set(x,y,z)或camera.position = new THREE.Vector3(x, y, z);
    控制相机的焦点位置,决定相机的朝向
    camera.lookAt(0, 0, 0);
    添加相机辅助工具来查看相机的位置

    灯光

    全局光:THREE.AmbientLight,影响整个scene的光源,一般是为了弱化阴影或调整整体色调,可设置光照颜色,以颜色的明度确定光源亮度;
    平行光:THREE.DirectionalLight,模拟类似太阳的光源,所有被照射的区域亮度是一致的,可设置光照颜色、光照方向(通过向量确定方向),以颜色的明度确定光源亮度;
    点光源:THREE.PointLight,单点发光,照射所有方向,可设置光照强度,光照半径和光颜色;
    聚光灯:THREE.SpotLight,这种光源有聚光的效果,类似于台灯,吊灯,手电筒。
    最简单的用法:

    function initLight() {  
      light = new THREE.DirectionalLight({ color: 0xffffff }); // 创建白色平行光  
      light.position.set(1, 0, 0); // 平行光只需设置方向向量,其他光源需要设置具体位置
      scene.add(light);  
    }
    

    光影关系可以显著影响显示效果。参考资料:https://www.cnblogs.com/amy2011/p/5761174.html

    3D模型

    我们可以用three自由地创建一些线几何体。或者加载一些已经做好的3D模型,three更新的很快,目前支持大部分格式的3D模型,以后会越来越多。

    function initObject() {
      // 添加一个圆柱体
      let geometry = new THREE.CylinderGeometry(100, 100, 300, 100, 100);
      let material = new THREE.MeshLambertMaterial({ color: 0xffff00 });
      mesh = new THREE.Mesh(geometry, material);
      mesh.position = new THREE.Vector3(0, 0, 0);
      scene.add(mesh);
    }
    

    CylinderGeometry是柱体,控制底面边的数量可以得到近似的圆柱体,还可以创建正方体文字等已经设定好的几何体。如果库里没有需要的,可以自己创建自定义几何体。


    function initCar() {  
      // 加载一个外部.obj汽车模型
      let mtlLoader = new THREE.MTLLoader();  
      mtlLoader.load('../../../3Dmodel/Lamborghini/Avent.mtl', (materials) => {  
        // 加载材料
        materials.preload();  
        let objLoader = new THREE.OBJLoader();  
        objLoader.setMaterials(materials);  
        objLoader.load('../../../3Dmodel/Lamborghini/Avent.obj', (object) => {// 加载模型  
            object.scale.set(80, 80, 80); // 放大倍数  
            scene.add(object);  
          }, (suc) => { console.log(((suc.loaded / suc.total) * 100) + '% OBJloaded'); }, (err) => { console.log(err); }  
        );  
      }, (suc) => { console.log(((suc.loaded / suc.total) * 100) + '% MTLloaded'); }, (err) => { console.log(err); });  
    }
    

    picture
    three.js加载外部文件需要用“loader系列”方法,通过这些方法可以加载.obj、.json、.dae等格式的模型(点击查看不同格式的模型之间的差异及优劣)。
    picture
    像这种将一张图片当作一个平面的,要用Texture加载材质(纹理)参考资料

    六、简单动画

    • 动画
      动画有两种方式,一种是让图像动,另一种是让相机动。
      一个简单的旋转

        function animate() {
          var v1 = new THREE.Vector3( 1, 1, 1 );
          meshAll.rotateOnAxis(v1,0.01);
          mesh.rotation.z -= 0.01;
          requestAnimationFrame(animate);
          renderer.render(scene,camera);
          stats.update();
        }
      
    • 性能检测
      为了监控帧率,引用Stats插件来监控动画的帧率
      picture

        <script src="Stats.js"></script>
        ……
        function initStats() {  
          stats = new Stats();  
          stats.domElement.style.position = 'absolute';  
          stats.domElement.style.top = '0px';  
          stats.domElement.style.left = '0px';  
          document.body.appendChild(stats.domElement);  
        }
      

    七、交互控制

    • dat.gui
      GUI
      资料:https://www.cnblogs.com/xiaoniuzai/p/6685556.html

    • 其它插件
      three自己也提供了很多插件来控制,例如OrbitControls,详情请看官网!

        function initControl() {
          controls = new THREE.OrbitControls(camera);
          // controls.enabled = false;// boolean,禁用控制器
          // controls.enableKeys = false; // boolean,禁用键盘
          // controls.autoRotate = true; // boolean,是否自动旋转,所有的旋转都是绕着场景中心旋转,不是原点
          // controls.autoRotateSpeed = 2; // Number,自动旋转速度
          controls.enableDamping = true; // boolean, 开启后有缓冲效果,具有物理的阻力感
          controls.dampingFactor = 0.3; // Float, 阻尼系数(0~1),数值越低,阻力越小
          // controls.enablePan = false; // boolean,禁止平移
          // controls..panSpeed = 0.5; // 平移速度
          // controls.enableRotate = false; // boolean,禁止旋转
          // controls.enableZoom = false; // boolean,禁止远近拉伸
          // controls.zoomSpeed = 0.1;// 鼠标滚动一个单位时拉伸幅度
          // controls.rotateSpeed = 0.5;// 旋转速度
          // controls.keyPanSpeed = 0.5; // Float, 用键盘平移的速度
          // controls.keys = {
          //   LEFT: 65,
          //   RIGHT: 68,
          //   UP: 87,
          //   BOTTOM: 83
          // }; // 键盘编码
          // controls.minAzimuthAngle = 0 * Math.PI; // 水平方向最小角度
          // controls.maxAzimuthAngle = 0.5 * Math.PI; // 水平方向最大角度,当Z轴向上时,从Z轴正方向往下看,逆时针90度
          // controls.minDistance = 500; // 相机离物体最近距离
          // controls.maxDistance = 600; // 相机离物体最远距离
          // controls.minPolarAngle = 0 * Math.PI;// 上下两极的可视区域最小角度
          // controls.maxPolarAngle = 0.5 * Math.PI;// 上下两极的可视区域最大角度,Z轴向上,从屏幕正上方往下90度
          // controls.mouseButtons = {
          //   ORBIT: THREE.MOUSE.LEFT,
          //   ZOOM: THREE.MOUSE.MIDDLE,
          //   PAN: THREE.MOUSE.RIGHT
          // }; // 鼠标键位设置
          // controls.screenSpacePanning = false; // boolean,false时只能在不是向上轴的方向移动。比如相机Z轴向上,那么物体只能在XY平面内移动
          // controls.target = new THREE.Vector3(300, 200, 0); // 相机聚焦坐标
        }  
      

    结束

    一个练习demo:一个采用 Three.js 的 3D 动画场景制作:飞行者
    这些只是入门资料整理,如果想做出官网展示的那些demo,还要自己下功夫钻研!让我们一起快乐地学习吧!

  • 相关阅读:
    linux 命令
    linux 命令
    linux 命令
    linux命令
    ubuntu 下安装ssh服务,并修改ssh端口
    爬虫基础
    Django之中间件
    Django之用户认证组件
    Django之cookie&session
    Django之forms组件
  • 原文地址:https://www.cnblogs.com/wz71014q/p/9203394.html
Copyright © 2020-2023  润新知