目录

  • 材质选择
  • 设置物体旋转方向和位置
  • 设置场景背景色
  • 添加坐标轴
  • 设置材质为线框 wireframe:true
  • 开启灯光阴影
  • 开始物体阴影
  • 开启平面接受阴影
  • 开启渲染器阴影
  • 控制阴影精细程度
  • 窗口自适应
  • 遍历
  • 强制设置所有材质
  • 雾化效果
  • 材质设置颜色
  • 材质两面可见
  • 以顶点颜色为基准色
  • 顶点创建面
  • 设置颜色
  • 高斯帕曲线 Gosper curve
  • 计算线段顶点之间的距离
  • 创建有多个材质的对象
  • applyMatrix
  • 获取name属性
  • 生成法向量
  • 贴图的使用jpg
  • 加载贴图
  • 加载obj模型
  • 加载gltf模型
  • 加载fbx模型
  • 设置光源
  • 画线轨迹
  • 画一个面
  • 移除模型
  • 经纬度转为坐标
  • 点击获取模型
  • .remove()和·dispose()方法区别
  • matrixAutoUpdate、updateMatrix
  • 控制器阻尼
  • 双击进入全屏和退出全屏
  • dat.GUI()
  • gamma
  • GLTFLoader.parse报错解决办法
  • threejs加载html元素
  • threejs点击mesh加载弹窗
  • 点击mesh元素发光
  • THREE.Line在某些角度消失
  • 加载scene背景图
  • 后期处理
  • 拖拽移动模型
  • 添加视频
  • 联合材质
  • 色调映射增加曝光
  • 点材质(PointsMaterial)
  • 点精灵材质(SpriteMaterial)
  • 传输帧数库 Stats.js
  • 操作实验库 dat.GUI
  • ThreeBSP布尔运算库
  • WebGLRenderer
  • 获取鼠标点击的三维坐标

材质选择

从左往右依次对应

MeshBasicMaterial(基础材质,不受光照影响)
MeshStandardMaterial(PBR标准材质)
MeshPhongMaterial(高光材质,适用于陶瓷,烤漆类质感)
MeshToonMaterial(卡通材质,俗称三渲二)
MeshStandardMaterial(PBR标准材质模拟金属反射)

设置物体旋转方向和位置

 //设置位置
plane.position.x=10;
plane.position.y=10;
plane.position.z=10;plane.position.set(10,10,10)plane.position=new THREE.Vector3(10,10,10)
//旋转
plane.rotation.x = -0.5 * Math.PI;plane.rotation.set(-0.5 * Math.PI,0,0)plane.rotation=new THREE.Vector3(-0.5 * Math.PI,0,0)
//如果想使用度数(0到360)设置旋转。
var degrees=45
var inRadius=degree * (Math.PI/180)
//平移
plane.translateX(4)

设置场景背景色

   renderer.setClearColor(new THREE.Color(0x000000));

添加坐标轴

 var axes = new THREE.AxesHelper(20);scene.add(axes);

设置材质为线框 wireframe:true

var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xFF0000,wireframe: true});

开启灯光阴影

spotLight.castShadow = true;
// 灯光阴影
// 1、材质要满足能够对光照有反应
// 2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
// 3、设置光照投射阴影 directionalLight.castShadow = true;
// 4、设置物体投射阴影 sphere.castShadow = true;
// 5、设置物体接收阴影 plane.receiveShadow = true;

注:接受阴影材质

 const material = new THREE.MeshPhongMaterial({ color: 0x808080, side: THREE.DoubleSide });

开始物体阴影

sphere.castShadow = true;

开启平面接受阴影

plane.receiveShadow = true;

开启渲染器阴影

renderer.shadowMap.enabled = true;

控制阴影精细程度

spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024);
spotLight.shadow.camera.far = 130;
spotLight.shadow.camera.near = 40;
spotLight.shadow.camera.fov = 30;

窗口自适应

window.addEventListener('resize', onWindowResize, false);
function resize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);renderer.setPixelRatio(window.devicePixelRatio);}

遍历

 scene.traverse(function (e) {console.log(e) //Scene Mesh AmbientLight SpotLight})

强制设置所有材质

见9.1.1

  scene.overrideMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});

雾化效果

两种

//颜色 near近处属性值  far远处属性值
scene.fog = new THREE.Fog(0xffffff, 10, 100);
//颜色 浓度
scene.fog = new THREE.FogExp2(0xffffff, 0.015);

材质设置颜色

  material.color.setStyle("#9370DB");

材质两面可见

var material = new THREE.MeshBasicMaterial({color: 0x0000ff, //颜色side: THREE.DoubleSide //两面可见
});

以顶点颜色为基准色

var material = new THREE.PointsMaterial({// 使用顶点颜色数据渲染模型,不需要再定义color属性// color: 0xff0000,vertexColors: THREE.VertexColors, //以顶点颜色为准size: 10.0 //点对象像素尺寸
});

顶点创建面

new THREE.Vector3(0, 0, 0) 表示坐标x:0,y:0,z:0

let p1 = new THREE.Vector3(0, 0, 0);
let p2 = new THREE.Vector3(10, 0, 0);
let p3 = new THREE.Vector3(0, 0, 10);
let p4 = new THREE.Vector3(10, 0, 10);

创建Geometry, 并将顶点添加到Geometry的顶点数组vertices中

let geometry = new THREE.Geometry();// 顶点添加到Geometry的顶点数组vertices中
geometry.vertices.push(p1, p2, p3, p4);

创建点模型对象

// 必须使用对应点的材质,size为点的大小let  material = new THREE.PointsMaterial( {color: 'red', size:2} );let  mesh = new THREE.Points( geometry, material );scene.add( mesh );

new THREE.Face3(0,2,1)

0,2,1:上面geometry.vertices.push(p1, p2, p3, p4)后geometry的下标索引值

let face1 = new THREE.Face3(0, 2, 1, new THREE.Vector3(), new THREE.Color(), 0);
let face2 = new THREE.Face3(1, 2, 3, new THREE.Vector3(), new THREE.Color(), 1);
var material = new THREE.MeshStandardMaterial( { color : 0x00cc00 } );//创建仅有一个三角面片的几何体
var geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) );
geometry.vertices.push( new THREE.Vector3(  50, -50, 0 ) );
geometry.vertices.push( new THREE.Vector3(  50,  50, 0 ) );//利用顶点 0, 1, 2 创建一个面
var normal = new THREE.Vector3( 0, 1, 0 ); //optional
var color = new THREE.Color( 0xffaa00 ); //optional
var materialIndex = 0; //optional
var face = new THREE.Face3( 0, 1, 2, normal, color, materialIndex );//将创建的面添加到几何体的面的队列
geometry.faces.push( face );//如果没有特别指明,面和顶点的法向量可以通过如下代码自动计算
geometry.computeFaceNormals();
geometry.computeVertexNormals(); // 通过平均面法线来计算顶点法线,效果更光滑scene.add( new THREE.Mesh( geometry, material ) );

Face3( a : Integer, b : Integer, c : Integer, normal : Vector3, color : Color, materialIndex : Integer )

a — 顶点 A 的索引。
b — 顶点 B 的索引。
c — 顶点 C 的索引。

normal — (可选) 面的法向量 (Vector3) 或顶点法向量队列。 如果参数传入单一矢量,则用该量设置面的法向量 .normal,如果传入的是包含三个矢量的队列, 则用该量设置 .vertexNormals

color — (可选) 面的颜色值 color 或顶点颜色值的队列。 如果参数传入单一矢量,则用该量设置 .color,如果传入的是包含三个矢量的队列, 则用该量设置 .vertexColors

materialIndex — (可选) 材质队列中与该面对应的材质的索引。

设置颜色

函数名 描述
set(value) 将当前颜色设置为指定的十六进制值。这个值可以是字符串、数值或是已有的THREE.Color实例
setHex(value) 将当前颜色设置为指定的十六进制值
setRGB(r,g,b) 根据提供的RGB值设置颜色。参数范围从0到1
setHSL(h,s,l) 根据提供的HSL值设定颜色。参数范围从0到1.
setStyle(style) 根据css设置颜色的方式来设置颜色。
copy(color) 从提供的颜色对象复制颜色到当前对象
copyGammaToLinear(color) 用THREE.Color提供的实例设置对象的颜色,颜色是由伽马色彩空间转换到线性色彩空间得来的。伽马色彩空间也使用RGB颜色,但是会使用指数系数而不是线性系数。
copyLinearToGamma(color) 用THREE.Color提供的实例设置对象的颜色。颜色是由线性色彩空间转换到伽马色彩空间得来的。
convertGammaToLinear() 将当前颜色从伽马色彩空间转换到线性色彩空间
convertLinearToGamma() 将当前颜色从线性色彩空间转换到伽马色彩空间
getHex() 以十六进制值形式从颜色对象中获取颜色值:435241
getHexString() 以十六进制字符串形式从颜色对象中获取颜色值:“0c0c0c”
getStyle() 以css值的形式从颜色对象中获取颜色值:“rgb(112,0,0)”
getHSL(optionalTarget) 以HSL值的形式从颜色对象中获取颜色值。如果提供了optionalTarget对象,Three.js将把h、s和l属性设置到该对象
offsetHSL(h,s,l) 将提供的h、s和l值添加到当前颜色的h、s和l上
add(color) 将r,g,b值添加到当前颜色
addColors(color1,color2) 将color1和color2相加,再将得到的值设置到当前颜色上
addScalar(s) 在当前颜色的RGB分量上添加值,谨记内部值范围从0到1
multiply(color) 将当前颜色的RGB值与THREE.color对象上的RGB值相乘
multiplyScalar(s) 将当前颜色RGB值与提供的RGB值相乘。谨记内部值范围从0到1
lerp(color,alpha) 找出介于对象的颜色和提供的颜色之间的颜色,aplha属性定义了当前颜色与提供颜色的差距
equals(color) 如果THREE.color对象实例提供的颜色的RGB值与当前颜色相等,则返回true
fromArray(array) 与setRGB方法具有相同的功能,只是RGB值可以通过数字数组的方式作为参数传入
toArray 返回三个元素的数组:[r,g,b]
clone() 复制当前颜色

高斯帕曲线 Gosper curve

var points = gosper(4, 60);

计算线段顶点之间的距离

//获取gosper曲线的x、y坐标点
var points = gosper(3, 60);//为每个坐标创建一个顶点,并把它们放在lines属性中
var lines = new THREE.Geometry();
//同时每个坐标还会计算一个颜色值,用来设置colors属性
var colors = [];
var i = 0;
points.forEach(function (e) {lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y));colors[i] = new THREE.Color(0xffffff);//这里使用setHSL()方法设置颜色(色调、饱和度、亮度)colors[i].setHSL(e.x / 100 + 0.5, (  e.y * 20 ) / 300, 0.8);i++;
});
lines.colors = colors;//使用虚线材质的话,必须调用 computeLineDistances()方法
lines.computeLineDistances();//创建线段基础材质
var material = new THREE.LineDashedMaterial({vertexColors: true,color: 0xffffff,dashSize: 2,gapSize: 2,scale: 2
});//通过创建的材质结合几何体即可创建一个 THREE.Line网格。
var line = new THREE.Line(lines, material);
line.position.set(25, -30, -60);
scene.add(line);

创建有多个材质的对象

 var meshMaterial = new THREE.MeshNormalMaterial();var wireFrameMat = new THREE.MeshBasicMaterial();// create a multimaterialvar plane = THREE.SceneUtils.createMultiMaterialObject(geom, [meshMaterial, wireFrameMat]);

applyMatrix

为每个对象创建一个Matrix4,然后我们将矩阵与该矩阵相乘以应用后续操作。

x轴移 -390,y轴移 -174。

   geom.applyMatrix(new THREE.Matrix4().makeTranslation(-390, -174, 0));

绕Z轴旋转-180° * 0.25=45°

sphere_matrix.multiply(new THREE.Matrix4().makeRotationZ(-Math.PI * 0.25));

获取name属性

cloud.name = "particles";scene.getObjectByName("particles")

生成法向量

geometry.computeFaceNormals();
geometry.computeVertexNormals();

贴图的使用jpg

  var textureGrass = THREE.ImageUtils.loadTexture("../assets/textures/ground/grasslight-big.jpg");//设置纹理的重复模式textureGrass.wrapS = THREE.RepeatWrapping;textureGrass.wrapT = THREE.RepeatWrapping;textureGrass.repeat.set(4, 4);// uv两个方向纹理重复数量var planeGeometry = new THREE.PlaneGeometry(1000, 200, 20, 20);var planeMaterial = new THREE.MeshLambertMaterial({map: textureGrass});var plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.receiveShadow = true;

加载贴图

普通贴图

material.map,替代颜色

法线贴图

material.normalMap,让细节程度较低的表面生成高细节程度的精确光照方向和反射效果

环境光遮蔽贴图

material.aoMap,用来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果

环境反射贴图

material.envMap,用于模拟材质反射周围环境的效果

  var textureLoader = new THREE.TextureLoader();var material = new THREE.MeshBasicMaterial({map: textureLoader.load('/assest/dot.png'),transparent: true, //使用背景透明的png贴图,注意开启透明计算// side: THREE.DoubleSide, //双面可见});

加载obj模型

// instantiate a loader
const loader = new OBJLoader();
// load a resource
loader.load(// resource URL'models/monster.obj',// called when resource is loadedfunction ( object ) {scene.add( object );},// called when loading is in progressesfunction ( xhr ) {console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );},// called when loading has errorsfunction ( error ) {console.log( 'An error happened' );}
);
    new MTLLoader().load("../models/gltf/QITA.mtl", (mtl) => {mtl.preload();const objLoader = new THREE.OBJLoader();objLoader.setMaterials(mtl);// 加载模型objLoader.load("../models/gltf/QITA.obj", (root) => {root.traverse((child) => {if (child instanceof THREE.Mesh) {child.material.side = THREE.DoubleSide;child.material = new THREE.MeshBasicMaterial({color: new THREE.Color("rgb(12,106,201)"),transparent: true,opacity: 0.2, //设置透明度});}});root.name = "fangzi"scene.add(root);});});

加载gltf模型

    var loader = new GLTFLoader();loader.load('/assest/model/little_chestnut/scene.gltf', res => {// 处理网格模型阴影const model = res.scene.children[0];model.traverse((n => {console.log(n);if (n?.isMesh) {n.castShadow = true;n.receiveShadow = true;if (n.material.map) n.material.map.anisotropy = 100// 提高纹理影映各项异型}}))scene.add(res.scene);render();})

如果模型经过DRACO压缩,则

import {DRACOLoader} from '../plugins/Three/module/jsm/loaders/DRACOLoader.js';
const dracoLoader = new DRACOLoader();dracoLoader.setDecoderPath('../data/');const loader = new GLTFLoader();loader.setDRACOLoader(dracoLoader);loader.load(url, function (gltf) {const obj = gltf.sceneobj.scale.set(0.1, 0.1, 0.1)obj.name = name + '-model'obj.position.x = position.x / 10;obj.position.z = position.z / -10;obj.rotation.y = position.rotatescene.add(obj);});

加载fbx模型

  var loader = new FBXLoader();loader.load('/assest/model/miku/miku.fbx', object => {object.scale.multiplyScalar(.1);scene.add(object);render();})

设置光源

   var spotLight = new THREE.SpotLight(0xffa95c, 4);spotLight.castShadow = true; //开启点光源阴影spotLight.shadow.bias = -0.0001; //减少阴影偏移率spotLight.shadow.mapSize.width = 10000;   //提高阴影映射宽高spotLight.shadow.mapSize.height = 10000;   //提高阴影映射宽高scene.add(spotLight)

画线轨迹

var lineMaterial = new THREE.LineBasicMaterial({color: 0xffffff});const lineGeometry = new THREE.BufferGeometry()const pointsArray = new Array()pointsArray.push(new THREE.Vector3(x, y, z))//点坐标//用这个api传入顶点数组lineGeometry.setFromPoints(pointsArray)var line = new THREE.Line(lineGeometry, lineMaterial);scene.add(line);

画一个面

 var pointsArr = [[0, 0],[0, 50],[50, 50],[50, 0],]var vector2Arr = [];// 转化为Vector2构成的顶点数组 二维向量pointsArr.forEach(elem => {vector2Arr.push(new THREE.Vector2(elem[0], elem[1]))});var shape = new THREE.Shape(vector2Arr);var material = new THREE.MeshBasicMaterial({color: 0x00ffff,side: THREE.DoubleSide, //两面可见}); //材质对象var geometry = new THREE.ShapeBufferGeometry(shape);var mesh = new THREE.Mesh(geometry, material); //网格模型对象scene.add(mesh); //网格模型添加到场景中

画多个面

 var pointsArrs = [[[0, 0],[0, 50],[50, 50],[50, 0],],[[60, 60],[250, 30],[200, 150],[20, 150],]]var shapeArr = [];//轮廓形状Shape集合pointsArrs.forEach(pointsArr => {var vector2Arr = [];// 转化为Vector2构成的顶点数组 二维向量pointsArr.forEach(elem => {vector2Arr.push(new THREE.Vector2(elem[0], elem[1]))});var shape = new THREE.Shape(vector2Arr);shapeArr.push(shape);});var material = new THREE.MeshBasicMaterial({color: 0x00ffff,side: THREE.DoubleSide, //两面可见}); //材质对象var geometry = new THREE.ShapeBufferGeometry(shapeArr);var mesh = new THREE.Mesh(geometry, material); //网格模型对象scene.add(mesh); //网格模型添加到场景中

移除模型

 scene.remove(scene.getObjectByName("chezi"))

经纬度转为坐标

 function getPosition(longitude, latitude, radius) {//经度,纬度,半径var lg = THREE.Math.degToRad(longitude);var lt = THREE.Math.degToRad(latitude);var temp = radius * Math.cos(lt);var x = temp * Math.sin(lg);var y = radius * Math.sin(lt);var z = temp * Math.cos(lg);return {x: x,y: y,z: z}}
 function createPosition(lnglat) {let spherical = new THREE.Sphericalspherical.radius = 100;const lng = lnglat[0]const lat = lnglat[1]const theta = (lng + 90) * (Math.PI / 180)const phi = (90 - lat) * (Math.PI / 180)spherical.phi = phi; // phi是方位面(水平面)内的角度,范围0~360度spherical.theta = theta; // theta是俯仰面(竖直面)内的角度,范围0~180度let position = new THREE.Vector3()position.setFromSpherical(spherical)return position}

点击获取模型

只有基础模型可获取

 addEventListener('click', onMouseDblclick, false);function onMouseDblclick(event) {// 获取 raycaster 和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前var intersects = getIntersects(event);// 获取选中最近的 Mesh 对象if (intersects.length !== 0 && intersects[0].object instanceof THREE.Mesh) {selectObject = intersects[0].object;//...do something} else {alert("未选中 Mesh!");}}// 获取与射线相交的对象数组function getIntersects(event) {event.preventDefault();// 声明 raycaster 和 mouse 变量var raycaster = new THREE.Raycaster();var mouse = new THREE.Vector2();// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;//通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置raycaster.setFromCamera(mouse, camera);// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前var intersects = raycaster.intersectObjects(scene.children);//返回选中的对象return intersects;}

.remove()和·dispose()方法区别

删除场景对象中Scene一个子对象Group,并释放组对象Group中所有网格模型几何体的顶点缓冲区占用内存

// 递归遍历组对象group释放所有后代网格模型绑定几何体占用内存
group.traverse(function(obj) {if (obj.type === 'Mesh') {obj.geometry.dispose();//废弃模型、材质obj.material.dispose();}
})
// 删除场景对象scene的子对象group
scene.remove(group);//删除对象
//终极奥义Threejs内存清除,清的渣都不剩
function disposeChild(mesh) {if (mesh instanceof THREE.Mesh) {if (mesh.geometry?.dispose) {mesh.geometry.dispose(); //删除几何体}if (mesh.material?.dispose) {mesh.material.dispose(); //删除材质}if (mesh.material?.texture?.dispose) {mesh.material.texture.dispose();}}if (mesh instanceof THREE.Group) {mesh.clear();}if (mesh instanceof THREE.Object3D) {mesh.clear();}}

matrixAutoUpdate、updateMatrix

默认情况下,matrixAutoUpdate属性设置为true,并且将自动重新计算矩阵。
如果对象是静态的,或者您希望在重新计算时手动控制,则可以通过将属性设置为false来获得更好的性能:

object.matrixAutoUpdate = false;
//更改任何属性后,手动更新矩阵:
object.updateMatrix();

控制器阻尼

鼠标滑动模型,有缓冲效果

orbitControl.enableDamping = true

双击进入全屏和退出全屏

window.addEventListener("dblclick",()=>{const fullScreenElement=document.fullscreenElement;if(!fullScreenElement){renderer.domElement.requestFullscreen()}else{domElement.exitFullscreen()}
})

dat.GUI()

const gui=new dat.GUI()
gui.add(cube.position,"x").min(0).max(5).step(0.01).name("移动x轴").onChange((value)=>{}).onFinishChange((value)=>{})//修改物体颜色
const params={color:"#ffffff",fn:()=>{gsap.to(cube.position,{x:5,duration:2,yoyo:true,repeat:1})}
}
gui.addColor(params,"color").onChange((value)=>{cube.material.color.set(value)
})
gui.add(cube,"visible").name("是否显示")
gui.add(params,"fn").name("立方体运动")var folder=gui.addFolder("设置文件夹")
folder.add(cube.material,"wireframe")

gamma

渲染计算后的模型仍在 linear 空间, 展示到屏幕时需要通过 gamma 校正, 将 linear 转换回 sRGB 空间, 也就是进行 gamma 校正, threejs 中可通过设置 gammaOutput 和 gammaFactor, 进行 gamma 校正, 校正后的 gamma2.2 颜色空间与 sRGB 相似.

// 定义 gammaOutput 和 gammaFactor
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;   // 电脑显示屏的 gammaFactor 为 2.2

GLTFLoader.parse报错解决办法

GLTFLoader.js:185 SyntaxError: Unexpected token < in JSON at position 0at JSON.parse (<anonymous>)at GLTFLoader.parse (GLTFLoader.js:315:21)at Object.onLoad (GLTFLoader.js:205:11)at three.module.js:39584:38

使用 import Flamingo from ‘./models/Flamingo.glb’ 导入模型

threejs加载html元素

import { CSS2DRenderer, CSS2DObject } from "../jsm/renderers/CSS2DRenderer.js";const earthDiv = document.createElement('div');earthDiv.className = 'label';earthDiv.innerHTML = 'Earth';earthDiv.style.marginTop = '0px';const earthLabel = new CSS2DObject(earthDiv);earthLabel.position.set(0, 1, 0);scene.add(earthLabel)labelRenderer = new CSS2DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight);labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = '0px';document.body.appendChild(labelRenderer.domElement);controls = new OrbitControls(camera, labelRenderer.domElement);labelRenderer.render(scene, camera);

threejs点击mesh加载弹窗

<body><div id="container"></div><div id="box" style="width: 200px;height: 200px;background-color: red;">111111111</div>
</body>import { CSS2DRenderer, CSS2DObject } from "../jsm/renderers/CSS2DRenderer.js";
let labelRenderer,labelCSS2DlabelRenderer = new CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.body.appendChild(labelRenderer.domElement);
labelCSS2D = new CSS2DObject(document.getElementById('box'));
scene.add(labelCSS2D);
labelCSS2D.visible = falsecontrols = new OrbitControls(camera, labelRenderer.domElement);window.addEventListener('click', onMouseClick, false);var raycaster = new THREE.Raycaster()
var mouse = new THREE.Vector2()function onMouseClick(event) {var vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);vector = vector.unproject(camera);var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());var intersects = raycaster.intersectObjects(scene.children);if (intersects.length) {console.log(intersects);const point = intersects[0].point;labelCSS2D.position.set(point.x - 0.01, point.y + 0.01, point.z - 0.03);labelCSS2D.visible = true} else {labelCSS2D.visible = false}}function render() {labelRenderer.render(scene, camera);renderer.render(scene, camera);}

点击mesh元素发光

import {FXAAShader  } from './jsm/shaders/FXAAShader.js'
import {EffectComposer  } from './jsm/postprocessing/EffectComposer.js'
import {RenderPass  } from './jsm/postprocessing/RenderPass.js'
import {ShaderPass  } from './jsm/postprocessing/ShaderPass.js'
import {OutlinePass  } from './jsm/postprocessing/OutlinePass.js'let composer, renderPass, outlinePass, effectFXAA;window.addEventListener('click', onMouseClick, false);var raycaster = new THREE.Raycaster()
var mouse = new THREE.Vector2()function onMouseClick(event) {var vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY /        window.innerHeight) * 2 + 1, 0.5);vector = vector.unproject(camera);var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());var intersects = raycaster.intersectObjects(scene.children);if (intersects.length) {addColor("0xDC143C", [intersects[0].object])}}const addColor = (color, selectedObjects) => {// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。composer = new EffectComposer(renderer)// 新建一个场景通道  为了覆盖到原理来的场景上renderPass = new RenderPass(scene, camera)composer.addPass(renderPass)// 物体边缘发光通道outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera)outlinePass.edgeStrength = 10.0 // 边框的亮度outlinePass.edgeGlow = 1 // 光晕[0,1]outlinePass.usePatternTexture = false // 是否使用父级的材质outlinePass.edgeThickness = 1.0 // 边框宽度outlinePass.downSampleRatio = 2 // 边框弯曲度outlinePass.pulsePeriod = 5 // 呼吸闪烁的速度outlinePass.visibleEdgeColor.set(parseInt(color)) // 呼吸显示的颜色outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色outlinePass.clear = truecomposer.addPass(outlinePass)// 自定义的着色器通道 作为参数effectFXAA = new ShaderPass(FXAAShader)effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)effectFXAA.renderToScreen = truecomposer.addPass(effectFXAA)outlinePass.selectedObjects = selectedObjectsreturn {composer, // composer在render循环函数中调用outlinePass // 实例化一次后设置  outlinePass.selectedObjects = selectedObjects}}//最后调用function animate() {controls.update()requestAnimationFrame(animate);render();stats.update();if (composer) {composer.render()}}

THREE.Line在某些角度消失

//如果更新线的顶点,则还必须更新线的边界球以进行平截头体剔除才能正常工作.
line.geometry.computeBoundingSphere();
//或者,您可以通过设置来防止对线进行视锥体剔除
line.frustumCulled = false;

加载scene背景图

const scene = new THREE.Scene();
scene.background = new THREE.CubeTextureLoader().setPath( 'textures/cubeMaps/' ).load( ['px.png','nx.png','py.png','ny.png','pz.png','nz.png'] );

后期处理

<!-- <script type="text/javascript" src="../libs/postprocessing/ShaderPass.js"></script> -->
<!-- <script type="text/javascript" src="../libs/shaders/CopyShader.js"></script> -->
<!-- <script type="text/javascript" src="../libs/postprocessing/EffectComposer.js"></script> -->
<!-- <script type="text/javascript" src="../libs/postprocessing/MaskPass.js"></script> -->
<!-- <script type="text/javascript" src="../libs/postprocessing/RenderPass.js"></script> -->//创建后期处理组合器
var renderer=new THREE.WebGLRenderer()
var composer=new THREE.EffectComposer(renderer)
composer.setSize(window.innerWidth, window.innerHeight);
//设置渲染场景
const renderPass = new THREE.RenderPass(scene, camera);
composer.addPass(renderPass);
// 特效通道
const effectCopy = new THREE.ShaderPass(THREE.CopyShader);
effectCopy.renderToScreen = true;
composer.addPass(effectCopy);// 渲染场景,更新控制器
const render = () => {// 渲染场景// 启用后期处理后,需要使用 composer.render// renderer.render(scene, camera);composer.render();// 控制器更新control.update();
}// 窗口尺寸变化
const resize = () => {width = window.innerWidth;height = window.innerHeight;camera.aspect = width / height;camera.updateProjectionMatrix();renderer.setSize(width, height);composer.setSize(width, height);
};

拖拽移动模型

//引入插件
import { DragControls } from "./jsm/controls/DragControls.js"; //拖拽控件
import { TransformControls } from "./jsm/controls/TransformControls.js"; //可视化平移控件var objects = [];//需要移动的所有模型const geo = new THREE.BoxGeometry(2, 2, 2);
const mat = new THREE.MeshBasicMaterial({color:0xdddddd});
const mesh = new THREE.Mesh(geo, mat);
mesh.name = "箱子"
objects.push(mesh)//将建立的模型放入需要移动的数组中
scene.add(mesh)const clickList = new DragControls(objects, camera, renderer.domElement);
clickList.addEventListener('drag', render);
clickList.addEventListener('dragstart', function (event) {controls.enabled = false;
});
clickList.addEventListener('dragend', function (event) {controls.enabled = true;
});//也可遍历scene获取需要拖拽的模型scene.traverse((e) => {console.log(e);if (e.name === "箱子") {objects.push(e)}})
  // 添加拖拽控件function initDragControls() {// 添加平移控件// var transformControls = new THREE.TransformControls(camera, renderer.domElement);// scene.add(transformControls);// 过滤不是 Mesh 的物体,例如辅助网格var objects = [];for (let i = 0; i < scene.children.length; i++) {if (scene.children[i].isMesh) {objects.push(scene.children[i]);}}// 初始化拖拽控件var dragControls = new THREE.DragControls(objects, camera, renderer.domElement);// 鼠标略过dragControls.addEventListener('hoveron', function (event) {transformControls.attach(event.object);});// 开始拖拽dragControls.addEventListener('dragstart', function (event) {controls.enabled = false;});// 拖拽结束dragControls.addEventListener('dragend', function (event) {controls.enabled = true;});}function init(){initDragControls()
}

添加视频

let video = document.createElement('video');
video.src = "1086x716.mp4"; // 设置视频地址
video.autoplay = "autoplay"; //要设置播放
// video对象作为VideoTexture参数创建纹理对象
var texture = new THREE.VideoTexture(video)
var geometry = new THREE.PlaneGeometry(108, 71); //矩形平面
var material = new THREE.MeshPhongMaterial({map: texture, // 设置纹理贴图
}); //材质对象Material
var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
scene.add(mesh);

联合材质

//    <script src="../../libs/examples/js/utils/SceneUtils.js"></script>function createMesh(geometry) {let meshMaterial = new THREE.MeshNormalMaterial();meshMaterial.side = THREE.DoubleSide;let wireFrameMaterial = new THREE.MeshBasicMaterial();wireFrameMaterial.wireframe = true;let circle = new THREE.SceneUtils.createMultiMaterialObject(geometry, [meshMaterial, wireFrameMaterial]);return circle;}

色调映射增加曝光

renderer.toneMapping = THREE.ReinhardToneMapping;//色调映射
renderer.toneMappingExposure = 5;//增加曝光
renderer.shadowMap.enabled = true; //启动阴影映射功能

## 6、灯光### 1.0光源的基类(Light)所有其他的光类型都继承了该类描述的属性和方法。Light( color : Integer, intensity : float )color - (可选参数) 16进制表示光的颜色。 缺省值 0xffffff (白色)。
intensity - (可选参数) 光照强度。 缺省值 1。属性```js
.color : Color
光源的颜色。如果构造的时候没有传递,默认会创建一个新的 Color 并设置为白色。.intensity : Float
光照的强度,或者说能量。 在 physically correct 模式下, color 和强度 的乘积被解析为以坎德拉(candela)为单位的发光强度。 默认值 - 1.0
.isLight : Boolean
用来校验这个类或者派生类是不是平行光。默认是 true。

方法

.copy ( source : Light ) : Light
从source复制 color, intensity 的值到当前光源对象中。.toJSON ( meta : String ) : JSON
以JSON格式返回光数据。

点材质(PointsMaterial)

Points使用的默认材质。

PointsMaterial( parameters : Object )

parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。

属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。

//This will add a starfield to the background of a scene
var starsGeometry = new THREE.Geometry();for ( var i = 0; i < 10000; i ++ ) {var star = new THREE.Vector3();star.x = THREE.Math.randFloatSpread( 2000 );star.y = THREE.Math.randFloatSpread( 2000 );star.z = THREE.Math.randFloatSpread( 2000 );starsGeometry.vertices.push( star );}var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } );var starField = new THREE.Points( starsGeometry, starsMaterial );scene.add( starField );

属性

.color : Color
材质的颜色(Color),默认值为白色 (0xffffff)。.isPointsMaterial : Boolean
用于检查此类或派生类是否为点材质。默认值为 true。因为其通常用在内部优化,所以不应该更改该属性值。.map : Texture
使用Texture中的数据设置点的颜色。.morphTargets : Boolean
材质是否使用morphTargets。默认值为false。.size : Number
设置点的大小。默认值为1.0。.sizeAttenuation : Boolean
指定点的大小是否因相机深度而衰减。(仅限透视摄像头。)默认为true。

点精灵材质(SpriteMaterial)

一种使用Sprite的材质。

SpriteMaterial( parameters : Object )

parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material 和 ShaderMaterial继承的任何属性)。

属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色), 内部调用Color.set(color)。 SpriteMaterials不会被Material.clippingPlanes裁剪。

var spriteMap = new THREE.TextureLoader().load( 'textures/sprite.png' );var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap, color: 0xffffff } );var sprite = new THREE.Sprite( spriteMaterial );
sprite.scale.set(200, 200, 1)scene.add( sprite );

属性

.color : Color
材质的颜色(Color),默认值为白色 (0xffffff)。 .map会和 color 相乘。.fog : boolean
材质是否受场景雾的影响。默认值为false。.lights : Boolean
材质是否受到光照的影响。默认值为 false。.map : Texture
颜色贴图。默认为null。.rotation : Radians
sprite的转动,以弧度为单位。默认值为0。.sizeAttenuation : Boolean
精灵的大小是否会被相机深度衰减。(仅限透视摄像头。)默认为true。

传输帧数库 Stats.js

initStats(type)

type参数:0:fps,1:ms,2:mb,3+:custom

var stats = initStats();stats = new Stats();
container.appendChild(stats.dom);function renderScene() {stats.update();requestAnimationFrame(renderScene);renderer.render(scene, camera);}

操作实验库 dat.GUI

 var gui = new dat.GUI();var controls = new function () {this.rotationSpeed = 0.02;this.bouncingSpeed = 0.03;};gui.add(controls, 'rotationSpeed', 0, 0.5);gui.add(controls, 'bouncingSpeed', 0, 0.5);var trackballControls = initTrackballControls(camera, renderer);
var clock = new THREE.Clock();
function render() {// update the stats and the controlstrackballControls.update(clock.getDelta());stats.update();// rotate the cube around its axescube.rotation.x += controls.rotationSpeed;cube.rotation.y += controls.rotationSpeed;cube.rotation.z += controls.rotationSpeed;// bounce the sphere up and downstep += controls.bouncingSpeed;sphere.position.x = 20 + (10 * (Math.cos(step)));sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));// render using requestAnimationFramerequestAnimationFrame(render);renderer.render(scene, camera);}
gui.add(sphere.position, "x").min(-5).max(5).step(0.1);
gui.add(spotLight, "angle").min(0).max(Math.PI / 2).step(0.01);
gui.add(spotLight, "distance").min(0).max(10).step(0.01);
gui.add(spotLight, "penumbra").min(0).max(1).step(0.01);
gui.add(spotLight, "decay").min(0).max(5).step(0.01);

ThreeBSP布尔运算库

three.js本身并没有提供用于几何体布尔运算的构造函数,需要借助一个库ThreeBSP.js实现。几何体的布尔运算可以借助数学中学习的差集、并集、交集概念去理解, 几何体之间的运算本质上就是两个顶点集合的运算,具体运算的算法可以查看计算几何学的理论内容,多数的三维软件基本都有布尔运算的相关命令, 尤其是机械类的三维建模软件,对于计算机辅助设计有兴趣的可以多研究。

//引入js库
//<script src="./ThreeJs/js/ThreeBSP.js"></script>/*** 创建网格模型*/
//几何体对象var cylinder = new THREE.CylinderGeometry(50,50,5,40);//圆柱var box = new THREE.BoxGeometry(40,5,40);//立方体//材质对象var material=new THREE.MeshPhongMaterial({color:0x0000ff});//网格模型对象var cylinderMesh=new THREE.Mesh(cylinder,material);//圆柱var boxMesh=new THREE.Mesh(box,material);//立方体//包装成ThreeBSP对象var cylinderBSP = new ThreeBSP(cylinderMesh);var boxBSP = new ThreeBSP(boxMesh);var result = cylinderBSP.subtract(boxBSP);//ThreeBSP对象转化为网格模型对象var mesh = result.toMesh();scene.add(mesh);//网格模型添加到场景中
方法 作用
intersrct 交集、重合的部分
union 并集、组合、相加
subtract 差集、相减

WebGLRenderer

let renderer = new THREE.WebGLRenderer({antialias: true, // true/false表示是否开启反锯齿alpha: true, // true/false 表示是否可以设置背景色透明precision: 'highp', // highp/mediump/lowp 表示着色精度选择premultipliedAlpha: false, // true/false 表示是否可以设置像素深度(用来度量图像的分辨率)preserveDrawingBuffer: true, // true/false 表示是否保存绘图缓冲maxLights: 3, // 最大灯光数stencil: false // false/true 表示是否使用模板字体或图案});
document.getElementById('threeCanvas').appendChild(renderer.domElement);
renderer.name = 'Renderer';
renderer.setClearColor(0xEEEEEE);
renderer.setSize(width, height);
renderer.toneMappingExposure = 5;//增加曝光
renderer.toneMapping = THREE.ReinhardToneMapping;//色调映射
renderer.shadowMap.enabled = true; //启动阴影映射功能

获取鼠标点击的三维坐标

  addEventListener('click', onDocumentMouseDown, false);function onDocumentMouseDown(event) {event.preventDefault();var vector = new THREE.Vector3();//三维坐标对象vector.set((event.clientX / window.innerWidth) * 2 - 1,- (event.clientY / window.innerHeight) * 2 + 1,0.5);vector.unproject(camera);var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());var intersects = raycaster.intersectObjects(scene.children);if (intersects.length > 0) {var selected = intersects[0];//取第一个物体console.log("x坐标:" + selected.point.x);console.log("y坐标:" + selected.point.y);console.log("z坐标:" + selected.point.z);}}

个人收藏,编写不易,给个小心心。

threejs个人笔记相关推荐

  1. Extjs 4.2 MVC+ThreeJs学习笔记(二)一个简单的ThreeJS场景

    ThreeJS基本要素 在我们用ThreeJS创建的3D世界里,会有很多的元素,然而以下四个是最基本的元素,也就是说只要包含了这些元素,就可以渲染出一个场景. 一个Scene(场景) 一个render ...

  2. Threejs学习笔记

    Three.js Three.js 学习笔记,来自: https://gitchat.csdn.net/columnTopic/5b320731bebc3c4bd7e725cb?utm_source= ...

  3. threejs学习笔记:实现导入的动画gltf模型播放动画

    这种方式需要gltf模型本身就带有动画,就是在建模的时候添加了动画,否则是不会生效的 只有一个动作 // 用于收集动画 const clock: THREE.Clock = new THREE.Clo ...

  4. threejs学习笔记:CSS2DObject 2d文字渲染

    import {CSS2DRenderer,CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer.js";/ ...

  5. Three-js 学习笔记(2)——几何体

    1,安装three npm install --s three 2,渲染几何图形 (1)添加vue元素 <template><div class="geometry_01& ...

  6. threejs 3d

    threejs学习笔记 1. 官网 2. 本地搭建官网 3. 新的打包工具(parcel) 官网 使用 4. 使用threejs去渲染第一个场景和物体 5. 添加轨道控制器 6. 坐标辅助器 7. 控 ...

  7. threejs 物体根据相机位置显示_Threejs学习笔记(一) 基础篇

    基本概念 此学习笔记主要记录使用threejs的制作http://sqace.163.com网站中用到的API和相关知识点. 一个完整的3D环境包含以下元素: 1.场景(Scene):是物体.光源等元 ...

  8. threejs 形状几何体_ThreeJS学习笔记(五)——二维几何体元素及穿梭动画

    二维几何体 ThreeJS可以创建三种二维几何体,包括CircleGeometry(圆形),PlaneGeometry(矩形),ShapeGeometry(自定义形状). 创建二维几何体和创建三维几何 ...

  9. Blender建模笔记 | 大帅老猿threejs特训

    写在前面 随着5G的普及网速变得越来快元宇宙的概念应然而生,需要多公司都开始搭建自己的沉浸式应用.搭建元宇宙项目的方案有很多种,比较常见的就是通过Threejs来实现.对于我们程序员由设计人员提供的模 ...

最新文章

  1. 思维dp ---- K步最短路 D. Explorer Space
  2. C#事件(event)解析
  3. 浏览器字体大小设置_全新内核 Edge 浏览器来了,这回或许能成为你的真 · 默认浏览器...
  4. 【Servlet3.0新特性】第03节_文件上传
  5. 倒果汁c语言,水果榨汁补维生素C?这些补维生素的错误别再犯了
  6. 条件编译#ifndef和#endif
  7. Oracle 分区表中索引失效
  8. Android MessageQueue与Message详解
  9. Nginx-代理服务器
  10. 【驱动详解】如何理解驱动程序
  11. 【JavaScript:快速入门】
  12. 初中教资计算机考试知识点,教资考试初中物理电学知识点总结来了
  13. 大丰银行:银行IPO被否第一家,宣告商业银行IPO的审核标准发生了重大变化
  14. 马的Hamilton周游路线问题
  15. 洛谷P2016 战略游戏 - 树形DP
  16. uni、uview复选框圆角
  17. FineReport11服务器部署包安装
  18. VBA之正则表达式(37)-- 去除无意义的零
  19. java计算机毕业设计仓储ERP系统源码+数据库+系统+lw文档+部署
  20. 《JUnit实战(第2版)》目录—导读

热门文章

  1. web音乐播放器+后台歌曲,歌单管理
  2. 《海量日志数据分析与应用》之数据加工:用户画像
  3. 在html5 里面做计算,HTML5 App实战(1):简单计算器
  4. Python3教程:pathlib 模块的用法
  5. 基于目标运动模型和观测模型的交互多模算法IMM卡尔曼滤波目标跟踪matlab仿真
  6. 拉格朗日乘子法、罚函数法、乘子罚函数法
  7. SPRINGBOOT服装商城
  8. Mask Scoring R-CNN论文解读
  9. 北京大学计算机801,【盛世清北】2021北京大学801计算机专业基础考研笔记
  10. 嵌入式开发前景怎么样?嵌入式开发有哪些优势?