threejs基本知识6 (重难点)
1、材质
基础网格材质(MeshBasicMaterial) 不受光照影响
Lambert网格材质(MeshLambertMaterial) 漫反射材质 无高光 受光照影响
Phong网格材质(MeshPhongMaterial) 高光材质 有高光 类似于镜面反射 受光照影响
标准网格材质(MeshStandardMaterial)PBR材质,物理材质 有金属度 和粗糙度 受光照影响
物理网格材质(MeshPhysicalMaterial) PBR材质,物理材质 有金属度 和粗糙度 增加清漆度(类似于车漆效果)和清漆粗糙度以及光折射率和透光率等等 受光照影响
材质具有共享的特性,如果多个模型公用一个材质,那么通过模型修改材质的属性,其他模型也会受到影响;可以通过材质克隆(clone)来解决该问题
2、灯光
AmbientLight(环境光 / 无阴影)
DirectionalLight(平行光 / 有阴影)
平行光两点确定方向,position为起点,平行光默认target指向原点(0,0,0)可以改变
设置平行光投射相机(正投影相机)的属性(阴影属性)
directionalLight.shadow.camera.near = 0.5 产生阴影的最近距离
directionalLight.shadow.camera.far = 500 产生阴影的最远距离
directionalLight.shadow.camera.left = -5 产生阴影距离位置的最左边位置
directionalLight.shadow.camera.right = 5 最右边
directionalLight.shadow.camera.top = 5 最上边
directionalLight.shadow.camera.bottom = -5 最下面
directionalLight.shadow.camera.mapSize.set(64,64) 模糊度 一般是2的n次方 值越大越清晰 越小越模糊
directionalLight.shadow.radius = 3 弱化阴影边缘锯齿
SpotLight(聚光灯 / 有阴影)
PointLight(点光源 / 有阴影)
阴影产生方式
mesh.castShadow = true 阴影的产生原型模型需要设置投影开启
mesh.receiveShadow = true 阴影的接收模型需要开启投影接收
renderer.shadowMap.enabled = true 渲染器开启阴影投射
3、坐标
本地坐标,模型自身的position值就是本地坐标
世界坐标,模型自身position值加上它父级position值总和
几何体通过平移、缩放、旋转会改变顶点坐标,几何体默认旋转会围绕几何中心旋转,当几何体顶点坐标发生变化时,旋转中心会发生变化
UV坐标,材质坐标,是二维坐标,横轴是U,纵轴是V,UV横纵轴取值范围都是0-1,位置类似于坐标轴第一象限;如果我们需要把一张图片的左下4/1贴在几矩形平面上,那么可以取UV的一半([0,0, 0,0.5, 0.5, 0.5, 0.5,0])
4、方法和属性
add()
父对象添加子对象
normalize()
向量归一化 方向不变 大小为1
remove()
父对象删除子对象
traverse()
递归遍历(深度遍历) 给场景添加该方法能递归遍历到所有的子对象
getObjectById()
通过对象id获取子对象
getObjectByName()
通过对象名称获取子对象
visible
对象隐藏或显示,网格mesh和材质material对象都有visible属性,都能显示或隐藏网格模型对象
getWorldDirection(vector)
相机获取视线方向并将方向数据写入vector
lerpColors
new three.Color().lerpColors(color1,color2,percent)
颜色混合 新color代表color1和color2的混合,percent代表color2所占的比值
5、模型
模型加载(GLTF加载器)时,可能会遇到模型材质颜色和实际渲染颜色有色差的问题,可以尝试进行如下配置:
第一种: renderer.outputColorSpace = THREE.SRGBColorSpace
第二种:renderer.outputEncoding = THREE.LinearEncoding / THREE.sRGBEncoding (需要与模型材质map的outputEncoding保持一致)
模型的恰当位置
相机控件(orbitControls),通过相机控件事先调整好模型渲染位置和尺寸,然后在渲染函数中拿到相机的position参数,以此作为相机初始位置
如果想把任意模型或位置作为画布的正中心,需要调整相机的target属性,同时也需要调整相机控件的target
模型的大小以及几何中心( three.Box3 包围盒 测量网格模型的大小 )
const box3 = new three.Box3()
box3..expandByObject(mesh)
const size = new three.vector3()
box3.getSize(size)
const center = new three.vector3()
box3.getCenter(center)
6、贴图
环境贴图(模拟周围环境反射的光照射到模型上)
材质设置envMap(单个模型材质用envMap)属性设置环境贴图,可以模拟出类似环境场景的模型效果,在亮色的环境贴图中,模型会呈现亮色,在暗色环境贴图中,模型会呈现暗色;如果要给整个场景设置公共的环境贴图,可以给scene场景environment属性添加贴图
立方体环境贴图 CubeTextureLoader
立方体有6个面,设置贴图方位顺序为x(右),-x(左),y(上),-y(下),z(后),-z(前)
7、顶点
position(位置)
normal(法线)
UV(uv)
color(颜色)
8、相机
up属性(修改后需要重新调整lookat目标 才能更新视图)
相机摆放姿态 默认是朝上(0,1,0)
up.set() 可以通过set方法修改
9、一些其他问题归纳
模型位置重合产生闪烁(深度冲突 z-fighting) 设置position不重合
相机太远了,产生闪烁(深度冲突 z-fighting) 设置renderer深度优化属性
锯齿问题
1、new THREE.WebGLRenderer({ antialias: true })
2、renderer.setPixelRatio(devicePixelRatio) 重新计算设备比
向量的点乘与叉乘
dot 点乘
crossVectors 叉乘(两个向量a,b的叉乘结果是一个向量c,且方向垂直向量a,b)
c = crossVectors(a,b)
计算两个向量的夹角
1、const cos = vector1.clone().normalize().dot(vector2.clone().normalize())
两个单位向量的点乘结果等于两个向量夹角的余弦值
2、const rad = Math.acos(cos)
通过余弦值可算出夹角的弧度值
3、const angle = THREE.MathUtils.radToDeg(rad)
通过弧度制可以算出夹角度数
实现球面任意一点与球面相切效果
position为球面任意一点位置,position向量归一后表示原点(0,0,0)朝position的方向
setFromUnitVectors方法由角度1旋转到角度2
var coordVec3 = new THREE.Vector3(position.x, position.y, position.z).normalize();
var meshNormal = new THREE.Vector3(0, 0, 1);
group.quaternion.setFromUnitVectors(meshNormal, coordVec3);
10、后期处理
后处理可能会引起模型颜色偏差,通过(伽马校正)可以解决
后处理可能带来锯齿问题 解决方式(fxaa,smaa)