threejs

链接:
【暮志未晚的博客,包含各种模型】:https://www.wjceo.com/blog/threejs/
【中文api】:http://techbrood.com/threejs/docs/
【官网api】:https://threejs.org/docs
【基础概念】:http://www.ituring.com.cn/book/miniarticle/49782
【郭隆邦】:http://www.yanhuangxueyuan.com/
【易百教程】:https://www.yiibai.com/webgl/webgl_graphics_basics.html
【林宏旭博客】:http://www.linhongxu.com/site/index?page=1
【在线编辑】:https://nunustudio.org/editor/index.html
【在线编辑】:https://playcanvas.com/editor/scene/678667

【web摄像头】:https://blog.csdn.net/lishundi/article/details/80604747
【web陀螺仪】:https://www.jianshu.com/p/5769075e9885
【陀螺仪+全景】:https://blog.csdn.net/Aimee1608/article/details/79403684【https://github.com/Aimee1608/3Drotate】【https://h5.xingyuanauto.com/201802/DealerYear/?hmsr=DealerYear】最后一个手机打开

1.场景(Scene):是物体、光源等元素的容器,可以配合 chrome 插件使用,抛出 window.scene即可实时调整 obj 的信息和材质信息。
2.相机(Camera):场景中的相机,代替人眼去观察,场景中只能添加一个,一般常用的是透视相机(PerspectiveCamera)
3.物体对象(Mesh):包括二维物体(点、线、面)、三维物体,模型等等
4.光源(Light):场景中的光照,如果不添加光照场景将会是一片漆黑,包括全局光、平行光、点光源等
5.渲染器(Renderer):场景的渲染方式,如webGL\canvas2D\Css3D。
6.控制器(Control): 可通过键盘、鼠标控制相机的移动

光源对象

光源类型:

环境光(没有特定方向,只有颜色),点光源(灯泡),平行光源(太阳光),聚光灯光源(手电筒)

颜色反射:

【物体白色,光源红色】:呈现红色(白色光源反射所有颜色光源)
【物体红色,光源蓝色】:呈现黑色(红色物体不会反射蓝色光源)

开启阴影[默认false,节约计算资源]:
   planeMesh.receiveShadow = true; [接收投影]
   mesh.castShadow = true;[产生投影]
   directionalLight.castShadow = true;[光源]
   renderer.shadowMap.enabled = true;[WebGL渲染器]
设置投影计算区域:

平行光【长方体区域】:

    directionalLight.shadow.camera.near = 0.5;
    directionalLight.shadow.camera.far = 300;
    directionalLight.shadow.camera.left = -50;
    directionalLight.shadow.camera.right = 50;
    directionalLight.shadow.camera.top = 200;
    directionalLight.shadow.camera.bottom = -100;

聚光【锥形区域】:

    spotLight.shadow.camera.near = 1;
    spotLight.shadow.camera.far = 300;
    spotLight.shadow.camera.fov = 20;
阴影模糊:

原因1:设置阴影对象的mapSize属性,增大
原因1:或者设置计算阴影的区域紧密包围在对象周围

光源设置:

光源颜色:

.color : Color 

光照强度:

ambient.intensity = 0.3;

从其它光源复制复制属性:

 .copy ( source : Light )

以JSON格式返回Light数据:

 .toJSON ( meta : String )

位置属性:

 position位置属性

平移方法:

  .translateX()沿着x轴平移
  .translateY()沿着y轴平移

光照距离(点光源、聚光光源,方向光、环境光不具有该属性):
1:从起点position开始衰减
2:默认0,意味着光线强度不会随着距离衰减

层级模型、树结构

递归遍历方法:

// 遍历场景对象scene  obj:每次遍历的对象
scene.traverse(function(obj) {
  // if (obj.type === "Group") {
  //   console.log(obj.name);
  // }
  // if (obj.type === "Mesh") {
  //   console.log('  ' + obj.name);
  //   obj.material.color.set(0xffff00);
  // }
  // if (obj.name === "左眼" | obj.name === "右眼") {
  //   obj.material.color.set(0x000000)
  // }
  // 打印id属性
  // console.log(obj.id);
  // 打印该对象的父对象
  // console.log(obj.parent);
  // 打印该对象的子对象
  // console.log(obj.children);
})

查找方法:

.getObjectByName ( name )

name —— 用于来匹配子物体中Object3D.name属性的字符串。
搜索该对象的子级,返回第一个带有匹配name的子对象。
请注意,大多数的对象中name默认是一个空字符串,要使用这个方法,你将需要手动地设置name属性。

.getObjectById ( id : Integer ) : Object3D

id —— 标识该对象实例的唯一数字。
搜索该对象的子级,返回第一个带有匹配id的子对象。
请注意,id是按照时间顺序来分配的:1、2、3、……,每增加一个新的对象就自增1。

纹理贴图

TextureLoader纹理加载器对象:

textureLoader.load('Earth.png', function(texture) {
    var material = new THREE.MeshLambertMaterial({
        // color: 0x0000ff,
        map: texture,// 设置纹理贴图:Texture对象作为材质map属性的属性值
      }); //材质对象Material
      var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      scene.add(mesh); //网格模型添加到场景中
      //纹理贴图加载成功后,调用渲染函数执行渲染操作
      // render();
    })

图片加载器ImageLoader:

    // 图片加载器
    var ImageLoader = new THREE.ImageLoader();
    // load方法回调函数,按照路径加载图片,返回一个html的元素img对象
    ImageLoader.load('Earth.png', function(img) {
      // image对象作为参数,创建一个纹理对象Texture
      var texture = new THREE.Texture(img);
      // 下次使用纹理时触发更新
      texture.needsUpdate = true;
      var material = new THREE.MeshLambertMaterial({
        map: texture, //设置纹理贴图
      });
      var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      scene.add(mesh); //网格模型添加到场景中
    });

协作:

webgl程序员只需要加载解析就可以
模型与贴图的对应关系,美术会设置好

视频作为纹理贴图:

// 创建video对象
    let video = document.createElement('video');
    video.src = "1086x716.mp4"; // 设置视频地址
    video.autoplay = "autoplay"; //要设置播放
    // video对象作为VideoTexture参数创建纹理对象
    var texture = new THREE.VideoTexture(video)
    var material = new THREE.MeshPhongMaterial({
      map: texture, // 设置纹理贴图
    }); //材质对象Material

法线贴图:

通过图片保留几何体表面的几何细节

好处:
低模+法线贴图=高模
降低模型大小,减少顶点的计算
节约顶点数量【简模:导出给程序员使用】

// TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
    var textureLoader = new THREE.TextureLoader();
    // 加载法线贴图
    var textureNormal = textureLoader.load('./法线贴图/3_256.jpg');
    var material = new THREE.MeshPhongMaterial({
      color: 0xff0000,
      normalMap: textureNormal, //法线贴图
      //设置深浅程度,默认值(1,1)。
      normalScale: new THREE.Vector2(3, 3),
    }); //材质对象Material

凹凸贴图:

图片像素的灰度值表示几何表面的高低深度
如果定义了法线贴图,则将忽略该贴图

    // TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
    var textureLoader = new THREE.TextureLoader();
    // 加载纹理贴图
    var texture = textureLoader.load('./凹凸贴图/diffuse.jpg');
    // 加载凹凸贴图
    var textureBump = textureLoader.load('./凹凸贴图/bump.jpg');
    var material = new THREE.MeshPhongMaterial({
      map: texture,// 普通纹理贴图
      bumpMap:textureBump,//凹凸贴图
      bumpScale:3,//设置凹凸高度,默认值1。
    }); //材质对象Material

MeshLambertMaterial、MeshBasicMaterial 没有凹凸、法线贴图属性,MeshPhongMaterial 有凹凸、法线贴图属性。

光照贴图添加阴影:

      //创建一个平面几何体作为投影面
      var planeGeometry = new THREE.PlaneGeometry(300, 200);
      planeGeometry.faceVertexUvs[1] = planeGeometry.faceVertexUvs[0];
      var textureLoader = new THREE.TextureLoader();
      // 加载光照贴图
      var textureLight = textureLoader.load('shadow.png');
      var planeMaterial = new THREE.MeshLambertMaterial({
        color: 0x999999,
        lightMap:textureLight,// 设置光照贴图
        // lightMapIntensity:0.5,//烘培光照的强度. 默认 1.
      }); //材质对象Material
      var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); //网格模型对象Mesh
      scene.add(planeMesh); //网格模型添加到场景中
      planeMesh.rotateX(-Math.PI / 2); //旋转网格模型
      planeMesh.position.y = -50; //设置网格模型y坐标

高光贴图:

      /**
       * 创建网格模型
       */
    //   var geometry = new THREE.BoxGeometry(100, 100, 100); //立方体
    //   var geometry = new THREE.PlaneGeometry(204, 102); //矩形平面
      var geometry = new THREE.SphereGeometry(100, 35, 35); //球体
      // TextureLoader创建一个纹理加载器对象,可以加载图片作为几何体纹理
      var textureLoader = new THREE.TextureLoader();
      // 加载纹理贴图
      var texture = textureLoader.load('earth_diffuse.png');
      // 加载高光贴图
      var textureSpecular = textureLoader.load('earth_specular.png');
      var material = new THREE.MeshPhongMaterial({
        // specular: 0xff0000,//高光部分的颜色
        shininess: 30,//高光部分的亮度,默认30
        map: texture,// 普通纹理贴图
        specularMap: textureSpecular, //高光贴图
      }); //材质对象Material
      var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      scene.add(mesh); //网格模型添加到场景中

环境贴图:

    /**
     * 创建网格模型
     */
    var geometry = new THREE.BoxGeometry(100, 100, 100); //立方体

    var loader = new THREE.CubeTextureLoader();
    // 所有贴图在同一目录下,可以使用该方法设置共用路径
    loader.setPath('环境贴图/');
    // 立方体纹理加载器返回立方体纹理对象CubeTexture
    var CubeTexture = loader.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
    //材质对象Material
    var material = new THREE.MeshPhongMaterial({
      envMap: CubeTexture, //设置环境贴图
      // 环境贴图反射率
      // reflectivity: 0.1,
    });
    console.log(CubeTexture.image);
    var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
    scene.add(mesh); //网格模型添加到场景中

数据纹理对象DataTexture:

 var geometry = new THREE.PlaneGeometry(128, 128); //矩形平面
      // var geometry = new THREE.BoxGeometry(128, 128,128); //立方体
      /**
       * 创建纹理对象的像素数据
       */
      var width = 32; //纹理宽度
      var height = 32; //纹理高度
      var size = width * height; //像素大小
      var data = new Uint8Array(size * 4); //size*4:像素在缓冲区占用空间
      console.log(data);
      for (let i = 0; i < size * 4; i += 4) {
        // 随机设置RGB分量的值
        data[i] = 255 * Math.random()
        data[i + 1] = 255 * Math.random()
        data[i + 2] = 255 * Math.random()
        // 设置透明度分量A
        data[i + 3] = 255 * 0.5
      }
      console.log(data);
      // 创建数据文理对象   RGBA格式:THREE.RGBAFormat
      var texture = new THREE.DataTexture(data, width, height, THREE.RGBAFormat);
      texture.needsUpdate = true; //纹理更新
      //打印纹理对象的image属性
      console.log(texture.image);
  
      var material = new THREE.MeshPhongMaterial({
        map: texture, // 设置纹理贴图
        transparent:true,//允许透明设置
      }); //材质对象Material
      var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
      scene.add(mesh); //网格模型添加到场景中

相机对象(投影方式)

分类:
正投影相机(小的场景,比如产品在线展示、机械、工业设计类三维建模软件模型的显示,物体不受物体与相机的距离影响)
透视投影相机(大的场景,比如游戏场景,随着距离的变化显示的大小会变化)

相机位置属性position
相机目标观察点:

.lookAt()方法

正投影相机OrthographicCamera:
构造函数参数:


1545197741313.jpg

1545197885347.jpg

透视投影相机PerspectiveCamera:
构造函数参数:


1545197939404.jpg
1545197959703.jpg

帧动画模块

播放动画:

    var loader = new THREE.ObjectLoader();
    var mixer = null; //声明一个混合器变量
    // 加载文件返回一个对象obj
    loader.load("model.json", function(obj) {
      console.log(obj)
      obj.scale.set(15, 15, 15);
      scene.add(obj);
      // obj作为混合器的参数,可以播放obj包含的帧动画数据
      mixer = new THREE.AnimationMixer(obj);
      // obj.animations[0]:获得剪辑clip对象
      // // 剪辑clip作为参数,通过混合器clipAction方法返回一个操作对象AnimationAction
      var AnimationAction = mixer.clipAction(obj.animations[0]);
      // AnimationAction.loop = THREE.LoopOnce; //不循环播放
      // AnimationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
      AnimationAction.play();
    });

混合器AnimationMixer:一个对象及其子对象的动画播放器
操作AnimationAction:设置播放方式、开始播放、暂停播放...

解析外部模型的的帧动画

不支持:比如stl、obj不支持

模型文件加载

加载FBX并解析骨骼动画

    var mixer=null;//声明一个混合器变量
    var loader = new THREE.FBXLoader();//创建一个FBX加载器
    loader.load("SambaDancing.fbx", function(obj) {
      // console.log(obj)
      scene.add(obj)
      obj.translateY(-80);
      // obj作为参数创建一个混合器,解析播放obj及其子对象包含的动画数据
      mixer = new THREE.AnimationMixer(obj);
      // 查看动画数据
      console.log(obj.animations)
      // obj.animations[0]:获得剪辑对象clip
      var AnimationAction=mixer.clipAction(obj.animations[0]);
      // AnimationAction.timeScale = 1; //默认1,可以调节播放速度
      // AnimationAction.loop = THREE.LoopOnce; //不循环播放
      // AnimationAction.clampWhenFinished=true;//暂停在最后一帧播放的状态
      AnimationAction.play();//播放动画
    })

WebGL渲染器

控制canvas大小:

renderer.setSize(width, height)

其它:

给模型添加事件

https://www.wjceo.com/blog/threejs/2018-02-13/60.html【其它例子】

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

function onMouseMove( event ) {
    // calculate mouse position in normalized device coordinates
    // (-1 to +1) for both components
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

}

function render() {
    // update the picking ray with the camera and mouse position
    raycaster.setFromCamera( mouse, camera );

    // calculate objects intersecting the picking ray
    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);

你可能感兴趣的:(threejs)