three.js小结

一、three.js核心概念

1.1 Scene (场景):包含灯光、相机、物体等其他一切需要交给three.js渲染的首层容器。

1.2 Camera (相机):相当于人眼,场景中的3D物体将以camera视角看到的2维形状进行展示。

常用类型

特点

OrthographicCamera

正交投影相机,视线为一组平行线。

PerspectiveCamera

透视投影相机,视线为从相机位置射出的一组同源射线。

1.3 Renderer (渲染器):与页面上canvas元素绑定,将scene中的内容绘制到canvas中。

二、three.js重要概念

2.1 物体:物体是由几何(Geometry)和材质(Material)两部分组成的,几何决定物体的形状,材质决定物体的颜色、光学特性等性质,物体在场景中也可以被渲染为点模型(Points)、线模型(Line)和网格模型(Mesh)三种。

绝大多数常见的几何形状,three.js都进行了封装,使用时只需要定义长宽高半径等基本要素即可。

常用的材质如下表所示。

材质

特点

点材质(PointsMaterial)

比较简单,只当需要绘制为点模型时使用,可以定义顶点的color、size等属性

线材质

LineBasicMaterial

绘制线模型时使用

LineDahedMaterial

产生虚线效果,可以设置虚线大小、间隔等参数

网格材质

MeshBasicMaterial

不受光照影响,没有棱角感

MeshLambertMaterial

会与光照产生漫反射,物体表面分界等地方会产生棱角感

MeshPhongMaterial

会与光照产生镜面反射,产生高光效果

精灵材质(SpriteMaterial)

本质上是一个与camara视线垂直的一个平面,当camera转动时,会自动保持垂直

自定义着色器材质(ShaderMaterial)

使用自定义shader渲染的材质,shader是用GLSL编写的小程序,运行于GPU。如果需要渲染内置Material之外的效果可以考虑使用这个。

2.2 光照:对自然界光照的模拟。常用的光照分为环境光、平行光、点光源和聚光灯。

灯光

特点

环境光(AmbientLight)

没有光源,环境光RGB成分分别和物体材质颜色RGB成分相乘

点光源(PointLight)

光线从光源位置向四周发散,光照强度会随着距离由近及远按衰减度衰减。

平行光(DirectionalLight)

通过position和target两个参数确定平行光方向,

聚光灯(SpotLight)

沿着特定方向逐渐发散的光源,照射范围在空间形成一个圆锥体

平行光漫反射简单数学模型:

漫反射光的颜色 = 网格材质颜色 ✖️ 入射光的颜色 ✖️光线入射角的余弦值

阴影的产生:阴影的产生需要进行三部分的设置,即光源的设置(castShadow. shadow.camera)、产生阴影物体的设置(castShadow)、接受阴影物体的设置(receiveShadow)。

2.3 纹理贴图

几何(Geometry)对纹理UV坐标将纹理贴图映射到几何的每个顶点,建立几何顶点和纹理贴图的映射关系,即可将纹理贴图的像素值转为几何顶点的颜色值等属性。

常用纹理贴图

纹理

用途

颜色贴图(map)

将贴图的每个像素点的GGB分量分别与该点的RGB分量相乘作为该点的颜色值。

凹凸贴图(bumpMap)

用图片像素的灰度值表示几何表面高低的深度,另外可以配合bumpScale参数作为凹凸高度。

法线贴图(normalMap)

从效果上讲和凹凸贴图的效果类似,但是法线贴图是以每个像素的RGB值影响每个像素片段的曲面法线,改变颜色照亮的方式,并不改变曲面的实际形状。配合normalScale(Vector2)参数使用。

透明贴图(alphaMap)

使用纹理的绿色通道控制表面的透明度

三、three.js坐标系

3.1 层级模型: three.js中,可以将若干个对象(物体、灯光或者其他组)放入一个组(Group)中,就形成了层级模型。所有的物体、灯光或者组,都会被包含在scene中,所以scene(场景)则是最外层。

3.2 坐标概念: 在scene中有一个基础的右手系3维坐标系,在scene没有旋转时,屏幕横向向右为x轴,纵向向上为y轴,屏幕向外为z轴。

局部坐标系:当直接给物体或者灯光时,其坐标为本地局部坐标,即以物体所属组的位置为原点的坐标。当物体直接添加到scene中时,其坐标即为世界坐标。

世界坐标系:物体相对于scene坐标原点的位置坐标。

观察坐标系:简单理解就是以camera视野观察到的空间坐标系。

裁剪坐标系:屏幕上可见的片段坐标系。

标准设备坐标系:世界坐标转为观察坐标,需要乘上视图矩阵;观察空间坐标转为裁剪坐标系,需要乘上相机投影矩阵。three.js中提供了一个Vector3.project(camera)方法综合这两步,得到标准设备坐标。

屏幕坐标系:three.js中即为canvas坐标系。

经纬度转为球坐标的计算

function lglt2xyz(lng: number, lat: number, radius: number) { 
    const theta = (90 + lng) * (Math.PI / 180); 
    const phi = (90 - lat) * (Math.PI / 180);
    return new THREE.Vector3().setFromSpherical( new THREE.Spherical(radius, phi, theta)); 
}

物体坐标转为屏幕像素坐标

局部坐标->世界坐标->标准设备坐标->屏幕坐标->像素坐标

局部坐标->世界坐标:物体坐标 + group坐标

世界坐标->标准设备坐标: Vector.project(camera)

标准设备坐标->屏幕坐标:((x + 1) / 2, ( 1 - y) / 2 )

屏幕坐标->像素坐标: 分别乘以canvas的宽高像素值。

function toScreenPosition( obj: THREE.Object3D, camera: THREE.Camera, width: number, height: number, ) { 
    const vector = new THREE.Vector3(); 
    const widthHalf = 0.5 * width; 
    const heightHalf = 0.5 * height; 
    obj.updateMatrixWorld(); 
    vector.setFromMatrixPosition(obj.matrixWorld); 
    vector.project(camera); 
    vector.x = (vector.x + 1) * widthHalf; 
    vector.y = -(vector.y - 1) * heightHalf; 
    return { x: vector.x, y: vector.y, z: vector.z, }; 
}

四、其他

4.1 轨道控制器(OrbitControls):使相机围绕目标进行轨道运动

function render() { 
    renderer.render(scene, camera); 
} 
render(); 
const controls = new THREE.OrbitControls(camera,renderer.domElement); controls.addEventListener('change', render);
function render() { 
    renderer.render(scene, camera); 
    requestAnimationFrame(render); 
} 
render();

4.2 Tween动画库

const box = document.createElement('div');
box.style.setProperty('background-color', '#008800');
box.style.setProperty('width', '100px');
box.style.setProperty('height', '100px');
document.body.appendChild(box);
function animate(time) { 
    requestAnimationFrame(animate);
    TWEEN.update(time);
} 
requestAnimationFrame(animate);
const coords = {x: 0, y: 0};
const tween = new TWEEN.Tween(coords).to({x: 300, y: 200}, 1000).easing(TWEEN.Easing.Quadratic.Out).onUpdate(() => { 
        box.style.setProperty('transform', `translate(${coords.x}px, ${coords.y}px)`)
});
tween.start()
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风xs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值