• home > webfront > visualization > Web3D >

    Web3D基础概念科普:Threejs基础概念解析

    Author:zhoulujun Date:

    Web3D基础概念入门Three js的第一步,就是认识场景Scene、相机Camera、渲染器Renderer三个基本概念。三维场景Scene三维场景(Scene)对象理

    Web3D基础概念

    入门Three.js的第一步,就是认识场景Scene、相机Camera、渲染器Renderer三个基本概念。

    三维场景Scene

    三维场景(Scene)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

    const scene = new THREE.Scene();// 创建3D场景对象Scene


    物体形状:几何体Geometry

    threejs 物体形状:几何体Geometry

    const geometry = new THREE.BoxGeometry(100, 100, 100); //创建一个长方体几何对象Geometry


    物体外观:材质Material

    fb2e04bd227a4717a51c00e4a103bf16~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75 (1).webp

    const material = new THREE.MeshBasicMaterial({//创建一个材质对象Material
        color: 0xff0000,//0xff0000设置材质颜色为红色
    });


    物体:网格模型Mesh

    实际生活中有各种各样的物体,在threejs中可以通过网格模型表示一个虚拟的物体,比如一个地板砖、一个房子。

    const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh

    两个参数分别为几何体geometry、材质material

    scene.add(mesh);

    在threejs中创建了一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中。

    62f0a91a56db44d1b623c072e3bdc820~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75 (1).webp



    模型位置.position
    const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
    mesh.position.set(0,10,0);//设置网格模型在三维空间中的位置坐标,默认是坐标原点


    透视投影相机

    Threejs如果想把三维场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera,就像你生活中想获得一张照片,需要一台用来拍照的相机。

    Threejs提供了正投影相机OrthographicCamera和透视投影相机PerspectiveCamera。根据场景对相机进行选择。

    透视投影相机PerspectiveCamera

    本质上就是在模拟人眼观察这个世界的规律。

    const camera = new THREE.PerspectiveCamera();// 实例化一个透视投影相机对象


    相机位置.position

    生活中用相机拍照,你相机位置不同,拍照结果也不同,threejs中虚拟相机同样如此。

    比如有一间房子,你拿着相机站在房间里面,看到的是房间内部,站在房子外面看到的是房子外面效果。

    camera.position.set(200, 200, 200); //相机在Three.js三维坐标系中的位置,根据需要设置相机位置具体值


    相机观察目标.lookAt()

    用相机拍照你需要控制相机的拍照目标,具体说相机镜头对准哪个物体或说哪个坐标。对于threejs相机而言,就是设置.lookAt()方法的参数,指定一个3D坐标。

    camera.lookAt(0, 0, 0); //坐标原点
    camera.lookAt(mesh.position);//指向mesh对应的位置

    相机观察目标指向Threejs 3D空间中某个位置

    a257058c94644b30ad4d76e18b09449e~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75.webp

    定义相机渲染输出的画布尺寸

    生活中相机拍照的照片是有大小的,对于threejs而言一样,需要定义相机在网页上输出的Canvas画布(照片)尺寸,大小可以根据需要定义。

    threejs虚拟相机渲染三维场景在浏览器网页上呈现的结果称为Canvas画布。

    const width = 800; //宽度
    const height = 500; //高度
    renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)

    定义相机输出画布的尺寸(单位:像素px)


    透视投影相机PerspectiveCamera:视锥体

    透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

    9bad08b69b624a0eb5d8a763bfd0e052~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75 (1).webp

    PerspectiveCamera( fov, aspect, near, far )


    参数含义默认 值
    fov相机视锥体竖直方向视野角度50
    aspect相机视锥体水平方向和竖直方向长度比,一般设置为Canvas画 布宽高比width / height1
    near相机视锥体近裁截面相对相机距离0.1
    far相机视锥体远裁截面相对相机距离,far-near构成了视锥体高 度方向 2000

    相机控件OrbitControls

    平时开发调试代码,或者展示模型的时候,可以通过相机控件OrbitControls实现旋转缩放预览效果。

    • 旋转:拖动鼠标左键

    • 缩放:滚动鼠标中键

    • 平移:拖动鼠标右键

    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';// 引入
    const controls = new OrbitControls(camera, renderer.domElement);// 使用
    // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
    controls.addEventListener('change', function () {
        renderer.render(scene, camera); //执行渲染操作
    });


    正投影相机

    正投影相机的长方体可视化空间和透视投影PerspectiveCamera视锥体相似,只是形状不同。

    b573175009c14ed39f7ad3eb1ea52329~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75.webp

    OrthographicCamera( left, right, top, bottom, near, far )// 构造函数格式
    参数(属 性)含义
    left渲染空间的左边界
    right渲染空间的右边界
    top渲染空间的上边界
    bottom渲染空间的下边界
    nearnear属性表示的是从距离相机多远的位置开始渲染,一般情况会设置 一个很小的值。默认值0.1
    farfar属性表示的是距离相机多远的位置截止渲染,如果设置的值偏小 小,会有部分场景看不到。默认值2000

    相机选择

    对于大部分需要模拟人眼观察效果的场景,需要使用透视投影相机,比如人在场景中漫游,或是在高处俯瞰整个园区或工厂。

    正投影没有透视效果,也就是不会模拟人眼观察世界的效果。在一些不需要透视的场景你可以选择使用正投影相机,比如整体预览一个中国地图的效果,或者一个2D可视化的效果。


    渲染器

    生活中如果有了景物和相机,那么如果想获得一张照片,就需要你拿着相机,按一下,咔,完成拍照。对于threejs而言,如果完成“咔”这个拍照动作,就需要一个新的对象,也就是WebGL渲染(WebGLRenderer)。

    WebGL渲染器WebGLRenderer

    const renderer = new THREE.WebGLRenderer();// 创建渲染器对象


    设置Canvas画布尺寸.setSize()

    // 定义threejs输出画布的尺寸(单位:像素px)
    const width = 800; //宽度
    const height = 500; //高度
    renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)


    渲染器渲染方法.render()

    渲染器WebGLRenderer执行渲染方法.render()就可以生成一个Canvas画布(照片),并把三维场景Scene呈现在canvas画布上面。

    renderer.render(scene, camera); //执行渲染操作


    渲染器Canvas画布属性.domElement

    渲染器WebGLRenderer通过属性.domElement可以获得渲染方法.render()生成的Canvas画布,.domElement本质上就是一个HTML元素:Canvas画布。

    document.body.appendChild(renderer.domElement);


    Canvas画布插入到任意HTML元素中
    <div id="webgl" style="margin-top: 200px;margin-left: 100px;"></div>
    
    document.getElementById('webgl').appendChild(renderer.domElement);


    Canvas画布布局和全屏

    threejs渲染输出的结果就是一个Cavnas画布,canvas画布也是HTML的元素之一,这意味着three.js渲染结果的布局和普通web前端习惯是一样的。

    非全屏局部布局

    <div id="webgl" style="margin-top: 100px;margin-left: 200px;"></div>
    
    // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
    const width = 800; //宽度
    const height = 500; //高度
    
    const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
    
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
    renderer.render(scene, camera); //执行渲染操作
    document.getElementById('wegbl').appendChild(renderer.domElement);


    全屏渲染

    // width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
    const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
    const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
    const renderer = new THREE.WebGLRenderer();
    document.body.appendChild(renderer.domElement);


    canvas画布宽高度动态变化

    // onresize 事件会在窗口被调整大小时发生
    window.onresize = function () {
        // 重置渲染器输出画布canvas尺寸
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 全屏情况下:设置观察范围长宽比aspect为窗口宽高比
        camera.aspect = window.innerWidth / window.innerHeight;
       //如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
        camera.updateProjectionMatrix();
    };


    三维坐标系

    三维笛卡尔坐标系是在 二维笛卡尔坐标系 的基础上根据右手定则增加 第三维坐标(即Z轴) 而形成的。

    175701787-f8dbed01f0154b89_fix732.webp

    three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的x、y、z轴,对于three.js的3D坐标系默认y轴朝上。

    94fa8eebc5b64c06965058abdec87580~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75.webp


    辅助观察坐标系

    Three.js提供了一个 AxesHelper 类,可以用来创建一个可视化的三维坐标系,可以用来辅助编写Three.js程序。

    const axesHelper = new THREE.AxesHelper(150);// 辅助观察的坐标系
    scene.add(axesHelper);

    本地(局部)坐标和世界坐标

    // mesh的世界坐标就是mesh.position与group.position的累加
    const mesh = new THREE.Mesh(geometry, material); 
    mesh.position.set(50, 0, 0);
    const group = new THREE.Group();
    group.add(mesh);
    group.position.set(50, 0, 0);
    1. 改变子对象的.position,子对象在3D空间中的坐标会发生改变。

    2. 改变父对象的.position,子对象在3D空间中的位置也会跟着变化,也就是说父对象.position和子对象.position叠加才是才是子对象的.position。

    任何一个模型的本地坐标(局部坐标)就是模型的.position属性。

    一个模型的世界坐标,说的是,模型自身.position和所有父对象.position累加的坐标。

    .getWorldPosition()获取世界坐标

    // 声明一个三维向量用来表示某个坐标
    const worldPosition = new THREE.Vector3();
    // 获取mesh的世界坐标,你会发现mesh的世界坐标受到父对象group的.position影响
    mesh.getWorldPosition(worldPosition);
    console.log('世界坐标',worldPosition);
    console.log('本地坐标',mesh.position);


    光源对物体表面影响

    实际生活中物体表面的明暗效果是会受到光照的影响,threejs中同样也要模拟光照Light对网格模型Mesh表面的影响。

    62f0a91a56db44d1b623c072e3bdc820~tplv-k3u1fbpfcp-jj-mark_3024_0_0_0_q75 (1).webp

    光源简介

    threejs 光源简介3d里面光源介绍

    为一个发光点,就像生活中一个灯泡以灯泡为中心向四周发射光线。

    //点光源:两个参数分别表示光源颜色和光照强度
    const pointLight = new THREE.PointLight(0xffffff, 1.0);
    
    //环境光:没有特定方向,整体改变场景的光照明暗
    const ambient = new THREE.AmbientLight(0xffffff, 0.4);
    
    // 平行光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    // 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
    directionalLight.target = mesh;


    动画渲染循环

    threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame实现动画渲染。

    请求动画帧window.requestAnimationFrame

    let i = 0;
    function render() {
        i+=1;
        console.log('执行次数'+i);
        requestAnimationFrame(render);//请求再次执行函数render
    }
    render();

    requestAnimationFrame实现周期性循环执行



    参考文章:

    Threejs入门教程和一些案例,看这一篇就够了!! https://juejin.cn/post/7376187709896917055#heading-25



    转载本站文章《Web3D基础概念科普:Threejs基础概念解析》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/visualization/threejs/9221.html