• 使用threejs绘制简单的3D图形


      首先,如果想要学习threejs,先去看看 官方基础教程 ,里面阐述了threejs的核心概念和一些重要的对象。这边文章就是具体使用threejs加入3D图形的一个水文,看了自由添加其他物体有个参照。

      使用threejs绘制3D图形,一般绘制的结果都是通过canvas元素生成,对于平面、3D效果、视角变化和交互、动画这一块,使用threejs可以快速便捷地帮助我们完成工作,而不必一步一步创建canvas,获取context再逐条绘制。threejs有一些基本概念在使用之前必须要了解。

      核心三大块:场景、相机、渲染器。作用分别为:在canvas中展示所有内容的3D容器、显示3D容器中可见区域的投影框、画面选定后进行拍照展示的渲染器。所有渲染器渲染时需要确定场景和相机。
      在实际进行绘制更加丰富的内容时,threejs提供了许多对象可以很快的完成一个复杂的3D图形,并且对于3D图像的灵活多变的调整。这些对象包括有几何形状、材料、光线、计时器、射线、辅助线、动画、音频、模型加载器、控制器等,除此之外还有例如矩阵、四元数等等一些进阶的运算,简单应用都不会涉及。
      首先创建三大核心对象:
      场景
      对于一个3D应用,场景应当是唯一的,所有相关的内容都应当添加到唯一的场景中,不管是要显示还是不显示的,显示的画面是通过调整相机角度决定的。所有场景就是所有具体内容的容器。
    const scene = new THREE.Scene();

       场景的初始化可以自定义其中一些内容,Scene接收对象形式的参数,比较有用属性的包括:

        * fog: 表示是否在场景中添加雾气效果,在3D空间中会变成一个有可见度的空间,默认值为null,可以设置一个Fog对象
        * overrideMaterial:默认值是null,可以设定一个Material对象,这样场景中所有的物体被渲染出来就会是设定的材料
     
      相机
      相机用于控制3D空间显示的区域,通常会采用显示距离的透视相机和显示投影的正交相机,当然以可以直接使用相机,并配置合适的参数来实现相应的相机。透视相机会根据场景中物体默认Z轴的深度进行近大远小的显示,而正交投影相机则会将远近不同的物体按正常的比例进行显示。
      普通相机直接使用:const camera = new THREE.Camera();
      3D场景汇总常用透视相机, 如果是生成一个透视相机,那么对于3D空间内同样大小但是Z轴距离不容的两个物体在相机中同时显示,更远的物体显示更小。
    const camera = new THREE.PerspectiveCamera(45, 1, 1, 100);
      透视相机默认接受4个参数,分别表示视角、截面纵横比, 近截面距离,远截面距离(具体参数解释看上面那个链接,还有模型可看)
      渲染器
      浏览器中3D效果展示是基于webGL的API,使用渲染器从名字上能够体现这一点
    const renderer = new THREE.WebGLRenderer();
      初始化是可以配备参数的:
        * canvas:传递一个canvas的dom元素,如果不传入,那么会新增画布,通过renderer.domElement来获取,画布用于展示绘制的内容
        * alpha: 画布默认是黑色背景,有时候我们只想要显示的内容有颜色,那么这一项就要设置为true
        * antialias:抗锯齿效果,顾名思义,默认为false
        * logarithmicDepthBuffer:这个值默认为false,是采用对数深度检测的内容,场景中物体离视野的距离不一,一般情况下在物体重叠时显示近的物体,特殊情况有可能深度判定有问题,前后材料有重叠破损的表现,此时就需要设置为true
     
      三个核心对象确定完毕,那么就和页面直接关联起来,设置画布大小并添加到body中:
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

       下面就粗暴地添加一组物体:

      所谓组的概念,是由于场景中3D图形是一个一个的,多个3D图形就可以组成一组,一个或者一组图形都可以通过name属性命名,并通过name找到对应的3D对象。对于一个场景中有多个模型,分组是十分必要的。

      添加一组物体,首先要有一个物体,物体有形状,有材料,要想显示材料就需要有光,更多地还需要确定物体的位置、旋转角度、缩放比例。想要显示还需要添加到场景中,相机正确就位,渲染器将相机定住的视野进行拍照渲染。
    let group = new THREE.Group();
    scene.add(group);
    
    // 添加两个物体
    let cube = new THREE.BoxGeometry( 10, 10, 10 );
    let boxMaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00, wireframe: true} );
    let box = new THREE.Mesh( cube, boxMaterial );
    box.position.x = 10;
    group.add( box );
    let sphere
    = new THREE.SphereGeometry( 5, 32, 32 ); let sphereMaterial = new THREE.MeshNormalMaterial({ wireframe: true, transparent: true} ); let blet = new THREE.Mesh( sphere, sphereMaterial ); blet.position.x = -10; group.add( blet ); // 添加光 let light = new THREE.AmbientLight( 0x404040 ); scene.add( light ); // 想要看到空间内的物体,需要调整一下距离和方位 camera.position.z = 100; // 更新空间需要重新渲染 renderer.render(scene, camera);

       Geometry对应有许多几何形状,大部分都进行封装,规则图形很好进行绘制,独特的图形也需要自己描点传入数据绘制,比如shape。

      材料又分许多种,这里材料都用到wireframe,便于观察我们添加的物体的确是3D结构。

      场景中有一个组,那么组内所有显示的3D对象都是在场景中的。而想要显示必须要确保视野对着物体,也就是camera的位置、角度都合适,然后有光才能看见材料的颜色。最后别忘了render一下。

      这时候场景中是这样的:

      好像3D想过也不是很明显,那么加上动画转一转,将两个物体延自身中心旋转:

    window.requestAnimationFrame(function animate() {
      requestAnimationFrame(animate);
      box.rotation.x += 0.01; 
      box.rotation.y += 0.01; 
      blet.rotation.x += 0.01;
      blet.rotation.y += 0.01;
      renderer.render(scene, camera)
    })

       差不多这样吧:

     

       更多用法参考:https://threejs.org/examples/

      还是很有意思的。。

  • 相关阅读:
    Redis QPS测试
    go语言下载及安装
    企业级Docker镜像仓库Harbor部署与使用
    Linux格式化数据盘
    【一周一Q】如何快速复制有规律内容
    聊一聊职业能力之执行力
    面试那些事
    使用gitlab时候 fork仓库不会实时从主仓库更新解决方案
    从给定字符串中提取姓名
    测试Websocket建立通信,使用protobuf格式交换数据
  • 原文地址:https://www.cnblogs.com/zzmiaow/p/9098086.html
Copyright © 2020-2023  润新知