目录
2.2.3、平行光(DirectionalLight)与环境光(AmbientLight)
2.4、动画渲染循环(requestAnimationFrame)
一、推荐链接
郭:Three.js教程 2024年新版本 配源码和电子书(私信获取) 持续更新中_哔哩哔哩_bilibili 或
three.js全网最全最新入门课程(2024年6月更新)【搞定前端前沿技术】_哔哩哔哩_bilibili
文档:
旧:Three.js电子书《Three.js零基础入门教程》_郭隆邦
找到想要的版本:比如r148:点击Assets下的Source code(zip)进行下载.
本地预览:vscode下载live-server插件,右键点击Open with Live Server运行到浏览器。
版本文档:项目docs文件夹下的index.html运行到浏览器,即可看到对应的中文文档。
案例:https://codepen.io/prisoner849/pen/RwyzrVj
二、基础案例
(理解)给景物拍照:scene是景物、camera是相机、render是“咔”完成拍照
2.1、三维坐标系
以html页面为例:
<body>
<div id="webgl" style="margin-top: 100px; margin-left: 200px"></div>
<!-- type="importmap" :.html文件中也能和nodeJs开发环境中一样的方式-->
<script type="importmap">
{
"imports": {
"three": "../../build/three.module.js",
"three/addons/": "../../examples/jsm/"
}
}
</script>
<script type="module" src="./index.js"></script>
</body>
index.js里:先引入three.js
import * as THREE from "three";
2.2、光源
2.2.1、光源对物体表面影响
2.2.2、点光源(PointLight)
// 材质对象Material
const material = new THREE.MeshLambertMaterial({
color: 0x0000ff, //设置材质颜色
transparent: true, //开启透明
opacity: 0.5, //透明度
});
const pointLight = new THREE.PointLight(0xffffff, 1.0); //创建光源对象 点光源
pointLight.decay = 0.0; //不随着距离的改变而衰减
pointLight.position.set(400, 0, 0); //光源的x、y、z坐标
scene.add(pointLight); // 将光源对象添加到场景中
const pointLightHelper=new THREE.PointLightHelper(pointLight,10)// 可视化点光源
scene.add(pointLightHelper)
2.2.3、平行光(DirectionalLight)与环境光(AmbientLight)
// 添加一个环境光
const ambient = new THREE.AmbientLight(0xffffff, 0.4);//颜色,亮度
scene.add(ambient);
// 添加一个平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position.set(50, 100, 50);
// directionalLight.target=mesh//默认坐标原点
scene.add(directionalLight);
const dirLightHelper = new THREE.DirectionalLightHelper(
directionalLight,
5,
0xffffff
); 可视化平行光
scene.add(dirLightHelper);
2.3、轨道控制器OrbitControls(相机控件)
让视图可以进行旋转、缩放、平移。
// 引入相机控件 轨道控制器OrbitControls【旋转、缩放效果】
import {OrbitControls} from 'three/addons/controls/OrbitControls.js'
//创建一个相机控件对象
const controls=new OrbitControls(camera,renderer.domElement);
controls.addEventListener('change',function(){
renderer.render(scene,camera);//随着相机位置的改变,不断执行渲染操作
})
注意:
如果默认camera.lookAt(0, 0, 0);则页面的中心点就是相机位置
如果lookAt()数值改变,相机控件也要随之改变:
controls.target.set(x,y,z) + controls.update()
2.4、动画渲染循环(requestAnimationFrame)
const clock=new THREE.Clock()
function render(){
const spt=clock.getDelta()*1000;//单位:毫秒
console.log("渲染帧率",1000/spt)
mesh.rotateY(0.01)
renderer.render(scene,camera)//一定要更新内容
requestAnimationFrame(render);//请求动画帧==实现周期性循环
}
render()
2.5、全屏渲染和全屏布局
注意:在做大屏时,页面边隙出现3~5px的空白,就设置margin为0。
=============index.js==============
const width = window.innerWidth;
const height = window.innerHeight;
=============index.html==============
<style>
body{
overflow: hidden;/* 不用滚动条*/
margin: 0px;/* 解决空白间隙问题*/
}
</style>
// 动态适配
window.onresize = function () {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
};
2.6、Stats(计算渲染帧率FPS)
创建大量物体时需要测试性能,加上它在当前页面左上角就会显示性能,点击可以切换不同模式
import Stats from "three/addons/libs/stats.module.js";
const stats = new Stats();
stats.setMode(2) //一共3种模式。默认0,还可以设置1、2
document.body.appendChild(stats.domElement);
2.7、简单立方体简介
2.7.1、阵列立方体
// 沿着x轴、y轴 建立阵列
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
const mesh = new THREE.Mesh(geometry, material); // 网格模型对象
mesh.position.set(i * 200, 0, j * 200); //x、y、z坐标
scene.add(mesh);// 将网格模型对象添加到场景中
}
}
2.7.2、常见图形演示
BoxGeometry(长方体)、SphereGeometry(球体)、CylinderGeometry(圆柱体)、
PlaneGeometry(矩形平面)、CircleGeometry(圆形平面)
const geometry = new THREE.BoxGeometry(50, 50, 50);//长方体
const geometry = new THREE.SphereGeometry(50);//球体
const geometry = new THREE.CylinderGeometry(50,50,100);//圆柱体
const geometry = new THREE.PlaneGeometry(100,50);//矩形平面
const geometry = new THREE.CircleGeometry(50); //圆形平面
备注:
在MeshBasicMaterial中添加 side:THREE.DoubleSide,可以让平面图形有“双面可见”效果
三、gui.js库(可视化改变三维场景)
GUI本质上相当于一个前端的JS库,add()里加啥,页面上出现啥。
通过domElement 改变相应的style属性。
3.1、颜色、命名、步长、事件
.addColor()改变颜色
.name()修改左侧的命名
.step()设置属性值改变的步长
.onChange()事件
// 光照强度属性.intensity
gui.add(ambient, "intensity", 0, 2.0).name("环境光强度").step(0.2);
gui.add(directionalLight, "intensity", 0, 2.0).name("平行光强度");
const obj = {
x: 30,
color: 0x00ffff,
};
gui.add(obj, "x", 0, 180).onChange(function (value) {
mesh.position.x = value;
renderer.render(scene, camera);
});
gui.addColor(obj, "color").onChange(function (value) {
material.color.set(value)
renderer.render(scene, camera);
});
3.2、下拉菜单、单选框
总结:
gui.add(参数1,'参数2',参数3)
参数1:操作对象
参数2:对象的具体属性
参数3:分为三种情况
如果是数字,则表示拖动条;
如果是数组/对象,则表示下拉菜单;
如果是布尔值,则表示单选框;
3.3、分组(addFolder)
关闭该组(close),默认打开。
const gui = new GUI();
gui.close()
const zu1 = gui.addFolder("光源系列");
zu1.add(ambient, "intensity", 0, 2.0).name("环境光强度").step(0.2);
zu1.add(directionalLight, "intensity", 0, 2.0).name("平行光强度");
zu1.close()
const zu2 = gui.addFolder("下拉框系列");
zu2.add(obj, "bool").name("是否旋转");
zu2.open() //可以不写,默认就是打开
===================addFolder套接============================
const folder01 = gui.addFolder("第一级");
const folder001 = folder01.addFolder("第一级下的第一组");
folder001.add() ...
四、基础语法总结
4.1、视锥体
理解:通过fov, aspect, near, far四个参数构成一个四棱台3D空间,就是视锥体。
注意:超出视锥体远裁界面的范围,会被剪裁(视觉上相当于隐藏)掉。
首先要有坐标系:AxesHelper
其次可以进行透视:PerspectiveCamera(fov, aspect, near, far)
最后通过lookAt()设置相机观察目标
4.2、光源
(已知)网格材质分为两类:
(1)、不受光照影响的材质:
MeshBasicMaterial(基础)
(2)、受光照影响的材质:
MeshLambertMaterial(漫反射)、MeshPhongMaterial(高光)
MeshStandardMaterial、MeshPhysicalMaterial(物理)
(因此)经常使用到的光源有以下四种:
AmbientLight(环境光):没有方向,整体高亮
PointLight(点光源)+PointLightHelper(可视化点光源)可配合使用
DirectionalLight(平行光):沿着特定方向平行发射+DirectionalLightHelper(可视化平行光)可配合使用
SpotLight(聚光灯)
最后:
通过new关键字可以实例化类(构造函数),获得一个对象,对象具有属性和方法。
在下载的项目文件夹下的examples文件夹下都是3D案例,在该文件夹右键“在文件中查找”,可以快速检索关键字。