threejs

鏈接:
【暮志未晚的博客,包含各種模型】:https://www.wjceo.com/blog/threejs/
【中文api】:http://techbrood.com/threejs/docs/
【官網(wǎng)api】:https://threejs.org/docs
【基礎(chǔ)概念】: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陀螺儀】:http://www.itdecent.cn/p/5769075e9885
【陀螺儀+全景】:https://blog.csdn.net/Aimee1608/article/details/79403684https://github.com/Aimee1608/3Drotate】【https://h5.xingyuanauto.com/201802/DealerYear/?hmsr=DealerYear】最后一個手機(jī)打開

1.場景(Scene):是物體、光源等元素的容器,可以配合 chrome 插件使用,拋出 window.scene即可實(shí)時調(diào)整 obj 的信息和材質(zhì)信息。
2.相機(jī)(Camera):場景中的相機(jī),代替人眼去觀察,場景中只能添加一個,一般常用的是透視相機(jī)(PerspectiveCamera)
3.物體對象(Mesh):包括二維物體(點(diǎn)、線、面)、三維物體,模型等等
4.光源(Light):場景中的光照,如果不添加光照場景將會是一片漆黑,包括全局光、平行光、點(diǎn)光源等
5.渲染器(Renderer):場景的渲染方式,如webGL\canvas2D\Css3D。
6.控制器(Control): 可通過鍵盤、鼠標(biāo)控制相機(jī)的移動

光源對象

光源類型:

環(huán)境光(沒有特定方向,只有顏色),點(diǎn)光源(燈泡),平行光源(太陽光),聚光燈光源(手電筒)

顏色反射:

【物體白色,光源紅色】:呈現(xiàn)紅色(白色光源反射所有顏色光源)
【物體紅色,光源藍(lán)色】:呈現(xiàn)黑色(紅色物體不會反射藍(lán)色光源)

開啟陰影[默認(rèn)false,節(jié)約計算資源]:
   planeMesh.receiveShadow = true; [接收投影]
   mesh.castShadow = true;[產(chǎn)生投影]
   directionalLight.castShadow = true;[光源]
   renderer.shadowMap.enabled = true;[WebGL渲染器]
設(shè)置投影計算區(qū)域:

平行光【長方體區(qū)域】:

    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;

聚光【錐形區(qū)域】:

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

原因1:設(shè)置陰影對象的mapSize屬性,增大
原因1:或者設(shè)置計算陰影的區(qū)域緊密包圍在對象周圍

光源設(shè)置:

光源顏色:

.color : Color 

光照強(qiáng)度:

ambient.intensity = 0.3;

從其它光源復(fù)制復(fù)制屬性:

 .copy ( source : Light )

以JSON格式返回Light數(shù)據(jù):

 .toJSON ( meta : String )

位置屬性:

 position位置屬性

平移方法:

  .translateX()沿著x軸平移
  .translateY()沿著y軸平移

光照距離(點(diǎn)光源、聚光光源,方向光、環(huán)境光不具有該屬性):
1:從起點(diǎn)position開始衰減
2:默認(rèn)0,意味著光線強(qiáng)度不會隨著距離衰減

層級模型、樹結(jié)構(gòu)

遞歸遍歷方法:

// 遍歷場景對象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的子對象。
請注意,大多數(shù)的對象中name默認(rèn)是一個空字符串,要使用這個方法,你將需要手動地設(shè)置name屬性。

.getObjectById ( id : Integer ) : Object3D

id —— 標(biāo)識該對象實(shí)例的唯一數(shù)字。
搜索該對象的子級,返回第一個帶有匹配id的子對象。
請注意,id是按照時間順序來分配的:1、2、3、……,每增加一個新的對象就自增1。

紋理貼圖

TextureLoader紋理加載器對象:

textureLoader.load('Earth.png', function(texture) {
    var material = new THREE.MeshLambertMaterial({
        // color: 0x0000ff,
        map: texture,// 設(shè)置紋理貼圖:Texture對象作為材質(zhì)map屬性的屬性值
      }); //材質(zhì)對象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場景中
      //紋理貼圖加載成功后,調(diào)用渲染函數(shù)執(zhí)行渲染操作
      // render();
    })

圖片加載器ImageLoader:

    // 圖片加載器
    var ImageLoader = new THREE.ImageLoader();
    // load方法回調(diào)函數(shù),按照路徑加載圖片,返回一個html的元素img對象
    ImageLoader.load('Earth.png', function(img) {
      // image對象作為參數(shù),創(chuàng)建一個紋理對象Texture
      var texture = new THREE.Texture(img);
      // 下次使用紋理時觸發(fā)更新
      texture.needsUpdate = true;
      var material = new THREE.MeshLambertMaterial({
        map: texture, //設(shè)置紋理貼圖
      });
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場景中
    });

協(xié)作:

webgl程序員只需要加載解析就可以
模型與貼圖的對應(yīng)關(guān)系,美術(shù)會設(shè)置好

視頻作為紋理貼圖:

// 創(chuàng)建video對象
    let video = document.createElement('video');
    video.src = "1086x716.mp4"; // 設(shè)置視頻地址
    video.autoplay = "autoplay"; //要設(shè)置播放
    // video對象作為VideoTexture參數(shù)創(chuàng)建紋理對象
    var texture = new THREE.VideoTexture(video)
    var material = new THREE.MeshPhongMaterial({
      map: texture, // 設(shè)置紋理貼圖
    }); //材質(zhì)對象Material

法線貼圖:

通過圖片保留幾何體表面的幾何細(xì)節(jié)

好處:
低模+法線貼圖=高模
降低模型大小,減少頂點(diǎn)的計算
節(jié)約頂點(diǎn)數(shù)量【簡模:導(dǎo)出給程序員使用】

// TextureLoader創(chuàng)建一個紋理加載器對象,可以加載圖片作為幾何體紋理
    var textureLoader = new THREE.TextureLoader();
    // 加載法線貼圖
    var textureNormal = textureLoader.load('./法線貼圖/3_256.jpg');
    var material = new THREE.MeshPhongMaterial({
      color: 0xff0000,
      normalMap: textureNormal, //法線貼圖
      //設(shè)置深淺程度,默認(rèn)值(1,1)。
      normalScale: new THREE.Vector2(3, 3),
    }); //材質(zhì)對象Material

凹凸貼圖:

圖片像素的灰度值表示幾何表面的高低深度
如果定義了法線貼圖,則將忽略該貼圖

    // TextureLoader創(chuàng)建一個紋理加載器對象,可以加載圖片作為幾何體紋理
    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,//設(shè)置凹凸高度,默認(rèn)值1。
    }); //材質(zhì)對象Material

MeshLambertMaterial、MeshBasicMaterial 沒有凹凸、法線貼圖屬性,MeshPhongMaterial 有凹凸、法線貼圖屬性。

光照貼圖添加陰影:

      //創(chuàng)建一個平面幾何體作為投影面
      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,// 設(shè)置光照貼圖
        // lightMapIntensity:0.5,//烘培光照的強(qiáng)度. 默認(rèn) 1.
      }); //材質(zhì)對象Material
      var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); //網(wǎng)格模型對象Mesh
      scene.add(planeMesh); //網(wǎng)格模型添加到場景中
      planeMesh.rotateX(-Math.PI / 2); //旋轉(zhuǎn)網(wǎng)格模型
      planeMesh.position.y = -50; //設(shè)置網(wǎng)格模型y坐標(biāo)

高光貼圖:

      /**
       * 創(chuàng)建網(wǎng)格模型
       */
    //   var geometry = new THREE.BoxGeometry(100, 100, 100); //立方體
    //   var geometry = new THREE.PlaneGeometry(204, 102); //矩形平面
      var geometry = new THREE.SphereGeometry(100, 35, 35); //球體
      // TextureLoader創(chuàng)建一個紋理加載器對象,可以加載圖片作為幾何體紋理
      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,//高光部分的亮度,默認(rèn)30
        map: texture,// 普通紋理貼圖
        specularMap: textureSpecular, //高光貼圖
      }); //材質(zhì)對象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場景中

環(huán)境貼圖:

    /**
     * 創(chuàng)建網(wǎng)格模型
     */
    var geometry = new THREE.BoxGeometry(100, 100, 100); //立方體

    var loader = new THREE.CubeTextureLoader();
    // 所有貼圖在同一目錄下,可以使用該方法設(shè)置共用路徑
    loader.setPath('環(huán)境貼圖/');
    // 立方體紋理加載器返回立方體紋理對象CubeTexture
    var CubeTexture = loader.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
    //材質(zhì)對象Material
    var material = new THREE.MeshPhongMaterial({
      envMap: CubeTexture, //設(shè)置環(huán)境貼圖
      // 環(huán)境貼圖反射率
      // reflectivity: 0.1,
    });
    console.log(CubeTexture.image);
    var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
    scene.add(mesh); //網(wǎng)格模型添加到場景中

數(shù)據(jù)紋理對象DataTexture:

 var geometry = new THREE.PlaneGeometry(128, 128); //矩形平面
      // var geometry = new THREE.BoxGeometry(128, 128,128); //立方體
      /**
       * 創(chuàng)建紋理對象的像素數(shù)據(jù)
       */
      var width = 32; //紋理寬度
      var height = 32; //紋理高度
      var size = width * height; //像素大小
      var data = new Uint8Array(size * 4); //size*4:像素在緩沖區(qū)占用空間
      console.log(data);
      for (let i = 0; i < size * 4; i += 4) {
        // 隨機(jī)設(shè)置RGB分量的值
        data[i] = 255 * Math.random()
        data[i + 1] = 255 * Math.random()
        data[i + 2] = 255 * Math.random()
        // 設(shè)置透明度分量A
        data[i + 3] = 255 * 0.5
      }
      console.log(data);
      // 創(chuàng)建數(shù)據(jù)文理對象   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, // 設(shè)置紋理貼圖
        transparent:true,//允許透明設(shè)置
      }); //材質(zhì)對象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場景中

相機(jī)對象(投影方式)

分類:
正投影相機(jī)(小的場景,比如產(chǎn)品在線展示、機(jī)械、工業(yè)設(shè)計類三維建模軟件模型的顯示,物體不受物體與相機(jī)的距離影響)
透視投影相機(jī)(大的場景,比如游戲場景,隨著距離的變化顯示的大小會變化)

相機(jī)位置屬性position
相機(jī)目標(biāo)觀察點(diǎn):

.lookAt()方法

正投影相機(jī)OrthographicCamera:
構(gòu)造函數(shù)參數(shù):


1545197741313.jpg

1545197885347.jpg

透視投影相機(jī)PerspectiveCamera:
構(gòu)造函數(shù)參數(shù):


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作為混合器的參數(shù),可以播放obj包含的幀動畫數(shù)據(jù)
      mixer = new THREE.AnimationMixer(obj);
      // obj.animations[0]:獲得剪輯clip對象
      // // 剪輯clip作為參數(shù),通過混合器clipAction方法返回一個操作對象AnimationAction
      var AnimationAction = mixer.clipAction(obj.animations[0]);
      // AnimationAction.loop = THREE.LoopOnce; //不循環(huán)播放
      // AnimationAction.clampWhenFinished=true;//暫停在最后一幀播放的狀態(tài)
      AnimationAction.play();
    });

混合器AnimationMixer:一個對象及其子對象的動畫播放器
操作AnimationAction:設(shè)置播放方式、開始播放、暫停播放...

解析外部模型的的幀動畫

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

模型文件加載

加載FBX并解析骨骼動畫

    var mixer=null;//聲明一個混合器變量
    var loader = new THREE.FBXLoader();//創(chuàng)建一個FBX加載器
    loader.load("SambaDancing.fbx", function(obj) {
      // console.log(obj)
      scene.add(obj)
      obj.translateY(-80);
      // obj作為參數(shù)創(chuàng)建一個混合器,解析播放obj及其子對象包含的動畫數(shù)據(jù)
      mixer = new THREE.AnimationMixer(obj);
      // 查看動畫數(shù)據(jù)
      console.log(obj.animations)
      // obj.animations[0]:獲得剪輯對象clip
      var AnimationAction=mixer.clipAction(obj.animations[0]);
      // AnimationAction.timeScale = 1; //默認(rèn)1,可以調(diào)節(jié)播放速度
      // AnimationAction.loop = THREE.LoopOnce; //不循環(huán)播放
      // AnimationAction.clampWhenFinished=true;//暫停在最后一幀播放的狀態(tài)
      AnimationAction.play();//播放動畫
    })

WebGL渲染器

控制canvas大?。?/p>

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);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • WebGL and Threejs: Lightig 什么是webgl和threejs? webgl是一個在瀏覽器...
    行陌路閱讀 6,157評論 0 2
  • 你和他 親愛的女孩 你不是不慎重 更不是風(fēng)花雪月 只是你的愛情 它在夢想和現(xiàn)實(shí)之間兩難 原來你曾傾心相待的男孩 他...
    喵爪爪閱讀 397評論 0 0
  • 有時,很想用一些文字來記錄下心情,但是抬起筆,又不知道該如何去寫,或許太多年沒有通過文字表達(dá)心情了,微商幾年,更是...
    靜小妞89閱讀 286評論 0 1
  • 這個年過得驚心動魄,從年前爸爸住院,我就每天都奔波在醫(yī)院和家以及去交警大隊的路上,爸爸年前出了交通事故,到現(xiàn)在在醫(yī)...
    重生之夏閱讀 249評論 0 0
  • “波聲漁笛。驚回好夢,夢里欲歸歸不得。”舊物不言,時光無聲。有些故事的打開,僅需一片落葉之瞬。章節(jié)散淡如風(fēng),...
    lM老師閱讀 501評論 0 0

友情鏈接更多精彩內(nèi)容