前言
接上篇,本篇把上篇代码拿来制作动画,顺便再过一下基本概念。上一篇有个地方写错了,就是npm安装的实际example之类的都有,只不过你需要指定位置导入。顺便说下这玩意到时候卸载也挺坑的,所有全局的变量到时候都得卸载了,到时候写项目应该封装起来,批量生成卸载
帧率检测器
threejs动画一般都是使用requestAnimationFrame。 我们需要把昨天那个球弹跳起来。顺便加入帧率检测器。 帧率检测器是stats,位置在:
'three/examples/jsm/libs/stats.module' ;
但是!!!这里面声明写的居然有问题??声明表示stats并不是一个类。经过查询issue后得知,尼玛官方意思要我们下另一个库https://www.npmjs.com/package/stats-js
npm i stats- js
官方表示这玩意就是用的他们的,我们不应该为他这个库去定义声明文件。。。 结果我去他那个库一看,尼玛都没人写声明。@types也没这玩意,直接声明个模块完了。 这个库用起来也很简单:
stats = new Stats ( ) ;
stats. setMode ( 0 ) ;
statsRef. current! . append ( stats. dom) ;
statsAnimate ( ) ;
function statsAnimate ( ) {
stats. begin ( ) ;
stats. end ( ) ;
requestAnimationFrame ( statsAnimate) ;
}
这样帧率检测器就渲染出来了。begin 和end 也可以换成update()实测也ok。不过这个帧率检测动画应该放到renderer.render下,不然单独抽个函数来放的话统计意义不大。
动画
let step = 0 ;
function statsAnimate ( ) {
stats. update ( ) ;
step += 0.04 ;
meshball. position. x = 20 + 10 * Math. cos ( step) ;
meshball. position. y = 2 + 10 * Math. abs ( Math. sin ( step) ) ;
renderer. render ( scene, camera) ;
requestAnimationFrame ( statsAnimate) ;
}
场景
scene.fog可以加个雾化,感觉好像用处不大:
scene.fog = new THREE.Fog(0xffffff, 0.005, 100);
scene.children可以拿到场景里东西,感觉比较实用。
console.log(scene.children);
几何体
vertices表示几何体顶点。是一个数组 faces表示几何体侧面 这是一个通过点和面加上材质来构建几何体的代码:
let vertices = [
new THREE. Vector3 ( 1 , 3 , 1 ) ,
new THREE. Vector3 ( 1 , 3 , - 1 ) ,
new THREE. Vector3 ( 1 , - 1 , 1 ) ,
new THREE. Vector3 ( 1 , - 1 , - 1 ) ,
new THREE. Vector3 ( - 1 , 3 , - 1 ) ,
new THREE. Vector3 ( - 1 , 3 , 1 ) ,
new THREE. Vector3 ( - 1 , - 1 , - 1 ) ,
new THREE. Vector3 ( - 1 , - 1 , 1 ) ,
] ;
let faces = [
new THREE. Face3 ( 0 , 2 , 1 ) ,
new THREE. Face3 ( 2 , 3 , 1 ) ,
new THREE. Face3 ( 4 , 6 , 5 ) ,
new THREE. Face3 ( 6 , 7 , 5 ) ,
new THREE. Face3 ( 4 , 5 , 1 ) ,
new THREE. Face3 ( 5 , 0 , 1 ) ,
new THREE. Face3 ( 7 , 6 , 2 ) ,
new THREE. Face3 ( 6 , 3 , 2 ) ,
new THREE. Face3 ( 5 , 7 , 0 ) ,
new THREE. Face3 ( 7 , 2 , 0 ) ,
new THREE. Face3 ( 1 , 3 , 4 ) ,
new THREE. Face3 ( 3 , 6 , 4 ) ,
] ;
let geo = new THREE. Geometry ( ) ;
geo. vertices = vertices;
geo. faces = faces;
geo. computeFaceNormals ( ) ;
let mater = [
new THREE. MeshLambertMaterial ( {
color: "red" ,
transparent: true ,
blending: THREE . MultiplyBlending,
} ) ,
new THREE. MeshBasicMaterial ( { color: "blue" } ) ,
] ;
let geomesh = SceneUtils. createMultiMaterialObject ( geo, mater) ;
scene. add ( geomesh) ;
其中3就是三角形的意思,6个面,每个面2个三角形拼成。 这方式费事,一般不会这么玩。 几何体一般分二维三维和多面几何体 二维矩形几何体,PlaneGeometry,前面做的例子底部就是这玩意。4参数,宽,高,宽度段数,高度段数。 二维圆几何体,CircleGeometry,radius 半经,segments 所用面数量,thetaStart 起始位,thetaLength,默认2派整圆。 三维立方体,以前叫cube 现在叫box ,和上面套路一样,后面几个参数是分段数。 三维球体,SphereGeometry 参数跟二维圆差不多。 圆柱体 CylinderGeometry 参数
/**
* @param [radiusTop=1] — Radius of the cylinder at the top.
* @param [radiusBottom=1] — Radius of the cylinder at the bottom.
* @param [height=1] — Height of the cylinder.
* @param [radiusSegments=8] — Number of segmented faces around the circumference of the cylinder.
* @param [heightSegments=1] — Number of rows of faces along the height of the cylinder.
* @param [openEnded=false] - A Boolean indicating whether or not to cap the ends of the cylinder.
* @param [thetaStart=0]
* @param [widthSegments=Math.PI * 2]
*/
球环几何体 TorusGeometry 就是个三维甜甜圈
/**
* @param [radius=1]
* @param [tube=0.4]
* @param [radialSegments=8]
* @param [tubularSegments=6]
* @param [arc=Math.PI * 2]
*/
TorusKnotGeometry 这个是跟麻花一样的图形,调整参数可以搞成闭环圆型麻花(传统麻花长条形)。 多面体 PolyhedronGeometry,vertices顶点,indices面,radius 大小,detail细节
/**
* @param vertices
* @param indices
* @param [radius=1]
* @param [detail=0]
*/
var verticesOfCube = [
- 1 , - 1 , - 1 , 1 , - 1 , - 1 , 1 , 1 , - 1 , - 1 , 1 , - 1 ,
- 1 , - 1 , 1 , 1 , - 1 , 1 , 1 , 1 , 1 , - 1 , 1 , 1 ,
] ;
var indicesOfFaces = [
2 , 1 , 0 , 0 , 3 , 2 ,
0 , 4 , 7 , 7 , 3 , 0 ,
0 , 1 , 5 , 5 , 4 , 0 ,
1 , 2 , 6 , 6 , 5 , 1 ,
2 , 3 , 7 , 7 , 6 , 2 ,
4 , 5 , 6 , 6 , 7 , 4
] ;
var geometry = new THREE. PolyhedronGeometry ( verticesOfCube, indicesOfFaces, 6 , 2 ) ;
threejs提供了一些内置多面体: IcosahedronGeometry 正20面 TetrahedronGeometry 正四面 OctahedronGeometry 正八面
网格对象
mesh,就是需要结合体加材质,然后出来的这个对象可以平移旋转之类。
相机
有个正交相机,透视相机。 简单说就是正交相机看啥都是大小相等,透视相机越远的东西越小。 fov就是第一个参数,是个张角,相当于你在a地看一个建筑,看到的建筑太高,不能看全貌,这时张角变大,大到能容纳整个建筑且位置不变,那就能看见全貌了。这玩意调大了类似于广角镜头拍出来的感觉。 长宽比就不用说了。通常是canvas横纵比
光源
有环境光、点光源、聚光灯、平行光、高级光照。 前面几个顾名思义,最后那个可以搞眩光之类的玩意 环境光:ambientLight , 这个主要还是看物体反射光线能力,如果物体可以反射光线,那么物体就会是啥颜色,如果反射不了,那么物体就会隐藏起来。 点光源:pointLight 可以设光照强度,距离之类,无阴影 聚光灯:spotLight castShadow为true就可以产生阴影,target决定方向,光照角度默认PI/3 平行光:DirectionalLight shadowmapheight 与shadowmapwidth可以调整阴影精细度。target可以new Object3d 设置个位置。 半球光源:HemisphereLight 主要是用于自然的光照效果。 平面光光源(RectAreaLight): 用来模拟像明亮的窗户或者条状灯光光源。 眩光光源 , 这玩意是example里的东西,并不是three导出的,和前面那个帧率检测器有点像,原理是要找个图片来当眩光,然后弄出效果。。
材质
材质通俗说就是贴图。 有基础材质,深度材质,法向材质,网格面材质,朗博材质,phong材质,着色器材质。 材质有基础属性,融合属性,高级属性。 基础属性有透明度,是否可见,过度描绘,名称,id,side可以使得材质贴哪面。 融合属性,可以怎样与背景融合,blender可以确定融合源,blandest融合目标,还有个融合公式。 高级属性,与webgl相关,一般不搞。 基础材质 meshBasicMaterial 不受光照影响,color 颜色,wireframe 显示线框 fog 是否受雾化影响。 深度材质:meshDepthMaterial 不受光照和材质决定,外观由物体到相机距离决定,可以与其他材质组合。 联合材质:createMultiMaterialObject,产生综合渲染效果。上面那个例子里就有用,需要使用blending来制作结合效果。比如使用深度材质,然后transparent为true,这样就可以和别的材质产生叠加效果。 法向材质: 这个就是开局搞得那个例子用的材质,是通过法向量计算颜色,感觉好像没啥用。 网格面材质:旧版有个专门的 meshFaceMaterial,现在没了,直接传数组,这个是用来绘制每个面的。
// 材质
meshMaterial = [];
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0x009e60, flatShading: true}));
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0x0051ba, flatShading: true}));
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0xffd500, flatShading: true}));
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0xff5800, flatShading: true}));
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0xc41e3a, flatShading: true}));
meshMaterial.push(new THREE.MeshBasicMaterial({color: 0xffffff, flatShading: true}));
cube = new THREE.Mesh(cubeGeometry, meshMaterial);
朗博材质:meshLambertMaterial 一般用于暗淡物体。 Phong材质:一般用于光亮物体。ambient反射能力,emissive自发光颜色。
动画与控件
import {TrackballControls}from 'three/examples/jsm/controls/TrackballControls'
关于这个控件的事件绑定,我发现了个坑,就是有时候平移旋转无效,后来研究发现就是监听绑定和three冲突了,包个div套上即可解决。 飞行控件 FlyControls(camera) 也是操控相机的玩意,有个移动速度可以一直前进,rollspeed转速,autoForward 自动前进 翻滚控件 RollControls(camera) 这个感觉区别不大。。 第一人称控件 FirstPersonControls(camera) 就是设计游戏那种视角。