最新文章:

您的位置: 富录-前端开发|web技术博客 > Three.js > 给新手的three.js入门讲解(二)

给新手的three.js入门讲解(二)

发布时间:2022年09月13日 评论数:抢沙发阅读数: 2950

    动作渲染
    原理
    对于Three.js 程序而言,动作渲染的实现是通过在秒中多次重绘画面实现的。FPS(Frames Per Second)指每秒画面重绘的次数。FPS 越大,则渲染效果越平滑,当 FPS 小于 20 时,一般就能明显感受到画面的卡滞现象。当 FPS 足够大(比如达到 60),再增加帧数人眼也不会感受到明显的变化,反而相应地就要消耗更多资源。
    setInterval 方法
    如果要设置特定的 FPS,可以使用该方法:
    setInterval(func, msec)
    其中, func 是每过 msec 毫秒执行的函数,如果将 func 定义为重绘画面的函数,就能实现动画效果。
    var id = setInterval(draw, 20);
    function draw() {
        mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
        renderer.render(scene, camera);
    } 
    这样,每 20 毫秒就会调用一次 draw 函数,改变长方体的旋转值,然后进行重绘。最终得到的效果就是 FPS 为 50 的旋转长方体。
    requestAnimationFrame 方法
    不在意多久重绘一次,就适合用 requestAnimationFrame 方法。它告诉浏览器在合适的时候调用指定函数,通常可能达到 60FPS。requestAnimationFrame 同样有对应的 cancelAnimationFrame 取消动画,使用方法类似clearInterval。
    由于 requestAnimationFrame 只请求一帧画面,与settimeout很相似。因此,除了在init 函数中需要调用,在被其调用的函数中需要再次调用 requestAnimationFrame :
    function draw() {
        mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
        renderer.render(scene, camera);
        var id = requestAnimationFrame(draw);
    }
    可以使用renderer.setAnimationLoop(callback)来代替requestAnimationFrame()。.callback 为每个可用帧都会调用的函数。 如果传入‘null’,所有正在进行的动画都会停止。对于WebVR项目,必须使用此函数。
    相机控件
    threejs 包括多个相机控件,每个控制都必须加载对应的控制器插件后才能使用。
    控制器要生效必须在renderer中使用代码更新
    var clock=new THREE.Clock();
    function render(){
        var delte=clock.getDelta();
        trackballControls.update(delta);
        requestAnimationFrame(render);
        webGLRenderder.render(scene,camera);
    }
    其中, THREE.Clock()对象可以获取一次渲染耗费的时间,调用clock.getDelta()会返回此次调用和上次调用之间的时间。
    OrbitControls
    可以使得相机围绕目标进行轨道运动。以舞台中心为中点,左右拖动屏幕会让镜头围绕着中心点旋转,镜头会看着中心点。
    OrbitControls( object : Camera, domElement : HTMLDOMElement )
    object: (必须)将要被控制的相机。该相机不允许是其他任何对象的子级,除非该对象是场景自身。
    domElement: (可选)用于事件监听的HTML元素,其默认值为整个文档, 但是如果你只希望在特定的元素上(例如Canvas上)进行控制,在这里进行指定即可。
    TrackballControls
    以模型或者点为中心, 围绕中心来展示。拖动模型后, 模型位置会变化, 但是摄像机 LookAt 的位置不会变化, 导致再次旋转模型将不再以模型为中心点。
    注意:使用相机控件,会导致相机lookAt()失效,需要设置OrbitControls.target为目标向量,比如
    controls.target = new THREE.Vector3(0,-1000,0);
    这样就可以看到视角更新为想要的视角啦。
    渲染
    WebGLRender
    使用WebGLRender对象能调动计算机显卡,计算指定相机角度下的scene样子进行渲染。
    var renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(0xEEEEEE);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio); 
    调用setClearColor(0xEEEEEE)将渲染器的背景色设置为白色,调用setSize()来控制渲染器渲染scene的范围。
    //将渲染的结果输出到指定页面元素中
    document.getElementById("WebGL-output").appendChild(renderer.domElement);
    //渲染场景
    renderer.render(scene, camera);
    渲染机制
    threejs的渲染器是基于webGL的。它的渲染机制是根据物体离照相机的距离来控制和进行渲染的。也就是说,它根据物体的空间位置进行排序,然后根据这个顺序来渲染物体。对于透明的物体,是按照从最远到最近的顺序进行渲染。
    控制渲染顺序
    1.设置
    renderer.sortObjects = false;
    这样,物体的渲染顺序将会由他们添加到场景中的顺序所决定。
    2.设置
    renderer.sortObjects = true;
    并且给特定的物体设置object.renderOrder 指定它的渲染顺序。默认renderOrder = 0;
    3.遍历设置
    material1.depthWrite = false;
    material2.depthWrite = false;
    辅助
    坐标轴AxesHelper
    用于简单模拟3个坐标轴的对象.
    红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
    var axesHelper = new THREE.AxesHelper( length );
    scene.add( axesHelper );
    length(可选的) 表示代表轴的线段长度. 默认为 1。
    性能检测stats
    检测当前场景的渲染帧率和显存占用情况;
    使用时,需要添加入渲染函数内:
    function Animate(){
        requestAnimationFrame(Animate);
        Render();
    }
    function Render(){
        stats.update();
        render.render(scene,camera);
    }
    动画
    动画混合器AnimationMixer
    动画混合器是用于场景中特定对象的动画的播放器。当场景中的多个对象独立动画时,每个对象都可以使用同一个动画混合器。
    AnimationMixer( Object3D )
    Object3D为混合器播放的动画所属的对象。
    属性
    .time : Number全局的混合器时间(单位秒; 混合器创建的时刻记作0时刻)
    .timeScale : Number全局时间(mixer time)的比例因子
    说明: 将混合器的时间比例设为0/1,可以暂停/取消暂停由该混合器控制的所有动作。
    方法
    clipAction (clip : AnimationClip, optionalRoot : Object3D) : AnimationAction//返回传入
    AnimationActionAnimationaction = mixer.clipAction(clip);
    clip是动画剪辑(AnimationClip)对象或者动画剪辑的名称(导入的模型的动作信息保存在object.animations[ ]数组内)。根对象Object3D可选,默认值为混合器的默认根对象。
    如果不存在符合传入的剪辑和根对象这两个参数的动作, 该方法将会创建一个。
    AnimationActions 用来调度存储在AnimationClips中的动画。动画剪辑AnimationClip是一个可重用的关键帧轨道集,它代表动画。
    AnimationAction的大多数方法都可以链式调用。
    点击交互
    原理
    浏览器是一个2D视口,在里面显示threejs的内容是3D场景,从浏览器观测3D场景时,眼睛就相当于是threejs内的摄像机点,鼠标在屏幕的点击位置是另一个点。这两个点会在threejs内连接成一条直线raycaster,直线穿过的threejs内的物体就是鼠标所点击的物体。
    实现
    Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float )
    origin —— 光线投射的原点向量。
    direction —— 向射线提供方向的方向向量,应当被标准化。
    near —— 返回的所有结果比near远。near不能为负值,其默认值为0。
    far —— 返回的所有结果都比far近。far不能小于near,其默认值为Infinity(正无穷)。
    方法
    .setFromCamera ( coords : Vector2, camera : Camera ) : null
    coords —— 在标准化设备坐标中鼠标的二维坐标 。
    camera —— 射线所来源的摄像机。
    使用一个新的原点和方向来更新射线。
    .intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array ) : Array
    objects —— 检测和射线相交的一组物体。
    recursive —— 若为true,则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分。默认值为false。
    optionalTarget —— (可选)(可选)设置结果的目标数组。如果不设置这个值,则一个新的Array会被实例化;如果设置了这个值,则在每次调用之前必须清空这个数组(例如:array.length = 0;)。
    检测所有在射线与这些物体之间,包括或不包括后代的相交部分。返回结果时,相交部分将按距离进行排序,最近的位于第一个),相交部分返回一个包含有交叉部分的数组:
    [ { distance, point, face, faceIndex, object }, ... ]
    distance —— 射线投射原点和相交部分之间的距离。
    point —— 相交部分的点(世界坐标)
    face —— 相交的面
    faceIndex —— 相交的面的索引
    object —— 相交的物体
    uv —— 相交部分的点的UV坐标。
    当计算这条射线是否和物体相交的时候,Raycaster将传入的对象委托给raycast方法。 这将可以让mesh对于光线投射的响应不同于lines和pointclouds。
    注意:对于网格来说,面必须朝向射线的原点,以便其能够被检测到。 用于交互的射线穿过面的背侧时,将不会被检测到。如果需要对物体中面的两侧进行光线投射, 需要将material中的side属性设置为THREE.DoubleSide。
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    function onMouseMove( event ) {
        // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    }
    function render() {
        // 通过摄像机和鼠标位置更新射线
        raycaster.setFromCamera( mouse, camera );
        // 计算物体和射线的焦点
        var intersects = raycaster.intersectObjects( scene.children );
        for ( var i = 0; i < intersects.length; i++ ) {
            intersects[ i ].object.material.color.set( 0xff0000 );
        }
        renderer.render( scene, camera );
    }
    window.addEventListener( 'mousemove', onMouseMove, false );
    window.requestAnimationFrame(render);
    基础库
    颜色
    构造器(Constructor)
    Color( r , g , b )
    .r : Float
    红色通道的值在0到1之间。默认值为1。
    .g : Float
    绿色通道的值在0到1之间。默认值为1。
    .b : Float
    蓝色通道的值在0到1之间。默认值为1。
    var color = new THREE.Color( 1, 0, 0 );
    使用十六进制定义一个颜色在three.js中是标准的方法
    var color = new THREE.Color( 0xff0000 );
    欧拉角
    欧拉角描述一个旋转变换,通过指定轴顺序和指定各轴旋转角度来旋转一个物体。
    构造器(Constructor)
    Euler( x : Float, y : Float, z : Float, order : String )
    x - (optional) 用弧度表示x轴旋转量。 默认值是 0。
    y - (optional) 用弧度表示y轴旋转量。 默认值是 0。
    z - (optional) 用弧度表示z轴旋转量。 默认值是 0。
    order - (optional) 表示旋转顺序的字符串,默认为'XYZ'(必须是大写)。
    var a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
    var b = new THREE.Vector3( 1, 0, 1 );
    b.applyEuler(a);
    三维几何线段
    构造器(Constructor)
    Line3( start : Vector3, end : Vector3 )
    start - 线段的起始点。默认值为 (0, 0, 0)。
    end - 线段的终点。默认值为 (0, 0, 0)。
    二维向量
    表示2D vector(二维向量),是一对有顺序的数字(标记为x和y)。
    Vector2( x : Float, y : Float )
    x - 向量的x值,默认为0。
    y - 向量的y值,默认为0。
    三维向量
    表示的是一个三维向量,是一个有顺序的、三个为一组的数字组合(标记为x、y和z)。
    构造函数
    Vector3( x : Float, y : Float, z : Float )
    x - 向量的x值,默认为0。
    y - 向量的y值,默认为0。
    z - 向量的z值,默认为0。
    四维矩阵
    在3D计算机图形学中,4x4矩阵最常用的用法是作为一个变换矩阵。三维空间中的向量Vector3通过乘以矩阵来进行转换,如平移、旋转、剪切、缩放、反射、正交或透视投影等。
    构造器(Constructor)
    Matrix4()
    平面
    在三维空间中无限延伸的二维平面
    构造器(Constructor)
    Plane( normal : Vector3, constant : Float )
    normal - (可选参数) 定义单位长度的平面法向量Vector3。默认值为 (1, 0, 0)。
    constant - (可选参数) 从原点到平面的有符号距离。 默认值为 0.
    射线
    构造函数
    Ray( origin : Vector3, direction : Vector3 )
    origin - (可选)Ray(射线)的原点,默认值是一个位于(0, 0, 0)的Vector3。
    direction - Vector3 Ray(射线)的方向。该向量必须经过标准化(使用Vector3.normalize),这样才能使方法正常运行。 默认值是一个位于(0, 0, 0)的Vector3。
    镜像
    在三维世界中,物体是经过某平面呈镜像的。同样的,设向量n是任意某平面的法线的单位向量,不考虑平移,其变换矩阵:
    0
    var m = new THREE.Matrix4();
    var vec=new THREE.Vector3(0,0,1);
    m.set( 1-2*vec.x*vec.x, -2*vec.x*vec.y, -2*vec.x*vec.z, 0,-2*vec.x*vec.y, 1-2*vec.y*vec.y, -2*vec.y*vec.z, 0,-2*vec.x*vec.z, -2*vec.y*vec.z, 1-2*vec.z*vec.z, 0,0, 0, 0, 1 );
    mesh.applyMatrix(m);
    mesh.translateZ(300);
    代码安全
    以上是three.js入门全部知识,至此已可使用three.js进行开发,h5游戏、微信小游戏、数字孪生、三维可视化,都可以使用three.js进行开发。
    Js是公开透明的代码,当使用three.js开发产品后,如要进行发布或交付,应当对js代码进行混淆加密,防止自己辛苦开发的产品被复制、盗用、攻击。
    JShaman是专业的js代码混淆加密工具,可以对js代码进行平展控制流、字符串阵列化加密、僵尸代码植入、AST重建等,加密后的代码安全、不可逆。
    结束
    本文是完整的three.js新手入门教程,推荐收藏。
二维码加载中...
本文作者:DGF      文章标题: 给新手的three.js入门讲解(二)
本文地址: https://arbays.com/post-194.html     本文已被百度收录!
版权声明:若无注明,本文皆为“富录-前端开发|web技术博客”原创,转载请保留文章出处。
挤眼 亲亲 咆哮 开心 想想 可怜 糗大了 委屈 哈哈 小声点 右哼哼 左哼哼 疑问 坏笑 赚钱啦 悲伤 耍酷 勾引 厉害 握手 耶 嘻嘻 害羞 鼓掌 馋嘴 抓狂 抱抱 围观 威武 给力
提交评论

清空信息
关闭评论