【three.js】threejs学习笔记(二)

前言

  • 接上篇,本篇把上篇代码拿来制作动画,顺便再过一下基本概念。上一篇有个地方写错了,就是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
			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);
}
  • 这个就是利用正弦余弦一直是1到-1之间来整动画。

场景

  • scene.fog可以加个雾化,感觉好像用处不大:
	scene.fog = new THREE.Fog(0xffffff, 0.005, 100);
  • scene.children可以拿到场景里东西,感觉比较实用。
	console.log(scene.children);

几何体

  • vertices表示几何体顶点。是一个数组
  • faces表示几何体侧面
  • 这是一个通过点和面加上材质来构建几何体的代码:
	let vertices = [
				//8顶点
				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自发光颜色。

动画与控件

  • 基础动画就是raf,这个不用说了。
  • tween.js动画库,可以创建补间动画,在最后update 网格即可。https://www.npmjs.com/package/@tweenjs/tween.js
  • 在example文件夹下有个control,里面有很多控件。
  • 轨迹球控件,这玩意是最常用的,就是滚轮可以缩放,鼠标可以左右拖动。
import {TrackballControls}from 'three/examples/jsm/controls/TrackballControls'
  • 关于这个控件的事件绑定,我发现了个坑,就是有时候平移旋转无效,后来研究发现就是监听绑定和three冲突了,包个div套上即可解决。
  • 飞行控件 FlyControls(camera) 也是操控相机的玩意,有个移动速度可以一直前进,rollspeed转速,autoForward 自动前进
  • 翻滚控件 RollControls(camera) 这个感觉区别不大。。
  • 第一人称控件 FirstPersonControls(camera) 就是设计游戏那种视角。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

业火之理

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

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

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

打赏作者

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

抵扣说明:

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

余额充值