Three.js快速入门

ThreeJS开发

该教程由本人学习记录下来的笔记供大家学习

  • 初识ThreeJS它是一个web端3D开发的好帮手
  • 本人对3D的热爱探索便前往学习了解了一番
  • 特此整理以下笔记供大家参阅

学习准备

这里我使用vue脚手架去创建的项目

目录结构:
在这里插入图片描述

安装

这里可以单独安装依赖,我这里安装好了,大家只需要在package.json中放入以下代码块

 "dependencies": {
    
    
    "dat.gui": "^0.7.9",
    "gsap": "^3.11.0",
    "three": "^0.143.0",
    "vue": "^3.0.4"
  },
  • three肯定是必不可少的
  • 其次dat.gui是three提供的一款gui界面调试的工具
  • gsap是一款动画库,用于实现动画
  • vue则是脚手架创建项目时自动安装好的

放入以上代码后则使用以下命令进行安装依赖

npm i

基本使用

这里简单使用three实现一个平面图形

在index.html中编写代码并且下方js文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Three开发---碰磕</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="./src/3D/threeBasic.js"></script>
</body>
</html>

threeBasic.js

1.引入three.js

import * as $Three from 'three'

2.创建一个场景

const scene= new $Three.Scene();

3.创建一个相机

const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

设置相机位置x,y,z并放入场景中

camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

4.添加物体

这里创建一个平面图形

//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

5.初始化渲染器

const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

6.将渲染的内容添加到dom节点中

document.body.appendChild(renderer.domElement)

7、使用渲染器,通过相机将场景渲染进来

renderer.render(scene,camera);

以上代码即可实现简单的效果

npm run dev

运行看看效果图吧!!!

效果图

在这里插入图片描述

现在开始一步一步系统学习吧!

控制器

使用控制器查看3d物体

这里我就直接贴代码了,代码中都给了注释,index.html中别忘了引入该js

/**
 * 使用控制器查看3d物体
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();
//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);

//编写渲染函数
function render(){
    
    
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

以上代码即可实现3D效果了,可拉近拉远,可旋转

物体移动

实现3d物体移动

/**
 * 实现3d物体移动
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);


//编写渲染函数
function render(){
    
    
    cube.position.x+=0.01;
    if(cube.position.x>5){
    
    
        cube.position.x=0
        
    }
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数
  • 通过new $Three.AxesHelper(5)创建了坐标轴,使得物体移动看着更清晰
  • 再通过控制position去修改它的位置

效果图

效果图如下:它是一直在动的哈

在这里插入图片描述

物体缩放与旋转

实现3d物体缩放

/**
 * 实现3d物体缩放
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);


//编写渲染函数
function render(){
    
    
    cube.position.x+=0.01;
    cube.scale.x+=0.01;//缩放scale
    cube.rotation.x+=0.01//旋转rotation
    if(cube.position.x>5){
    
    
        cube.position.x=0
        cube.scale.x=1
        cube.rotation.x=0
    }
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数
  • 旋转通过控制rotation属性
  • 缩放通过控制scale属性

以上代码即可看到该图形边变长边旋转…

Clock跟踪时间

/**
 * Clock跟踪时间
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//设置时钟
const clock=new $Three.Clock();

//编写渲染函数
function render(){
    
    
    //获取时钟运行的总时长
    let time=clock.getElapsedTime();
    let deltaTime=clock.getDelta();
    // console.log("时钟运行总时长:",time);
    // console.log("两次获取时间的间隔::",deltaTime);
    let t=time%5;
    cube.position.x =t*1;
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数
  • 以上代码主要是运用一下Three中的Clock()时钟

Gsap动画

gsap设置各种动画效果

官网:https://github.com/greensock/GSAP

如果没安装该依赖则手动安装一下,跟着教程的话一开始即安装好了,没有安装请安装

npm install gsap

开始使用:

/**
 * gsap设置各种动画效果
 * npm install gsap
 * 官网:https://github.com/greensock/GSAP
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//导入动画库
import gsap from 'gsap'
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

//修改几何体的位置
// cube.position.set(5,0,0)
// cube.position.x=3;
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//设置时钟
// const clock=new $Three.Clock();

//设置动画to(物体的属性,{需要执行的操作..},ease执行方式,repeat:重复的次数(死循环设置-1),yoyo:往返移动,delay:延迟移动,onComplete:()=>完成执行的回调函数,onStart:()=>动画开始执行)
var maveposition=gsap.to(cube.position,{
    
    x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
    
    
    console.log("移动完成")
},
onStart:()=>{
    
    
    console.log("动画开始")
}
});
window.addEventListener('click',()=>{
    
    
    //isActive()表示是否在运行移动
    if(maveposition.isActive()){
    
    
        maveposition.pause();//动画暂停
    }else{
    
    
        maveposition.resume();//动画继续
    }
})
gsap.to(cube.rotation,{
    
    x:2*Math.PI,duration:6,ease: "power1.inOut"})

//编写渲染函数
function render(){
    
    
    
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数
  • 如何使用代码中都进行了注释,自行看看咯

自适应

以上代码均没有做一个自适应处理

  • 当你放大缩小页面时,页面内容还是保持不变,所以我们要解决这个问题!!!
  • 通过监听画面变化,更新画面
/**
 * 页面自适应
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//导入动画库
import gsap from 'gsap'
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

//修改几何体的位置
// cube.position.set(5,0,0)
// cube.position.x=3;
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//设置动画to(物体的属性,{需要执行的操作..},ease执行方式,repeat:重复的次数(死循环设置-1),yoyo:往返移动,delay:延迟移动,onComplete:()=>完成执行的回调函数,onStart:()=>动画开始执行)
var maveposition=gsap.to(cube.position,{
    
    x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
    
    
    console.log("移动完成")
},
onStart:()=>{
    
    
    console.log("动画开始")
}
});
window.addEventListener('click',()=>{
    
    
    //isActive()表示是否在运行移动
    if(maveposition.isActive()){
    
    
        maveposition.pause();//动画暂停
    }else{
    
    
        maveposition.resume();//动画继续
    }
})
gsap.to(cube.rotation,{
    
    x:2*Math.PI,duration:6,ease: "power1.inOut"})

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
})
  • resize表示页面大小被改变时触发的事件

Gui

通过gui界面更改参数

没安装的话请安装

npm install --save dat.gui

使用:

/**
 * gui界面更改参数
 * npm install --save dat.gui
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//导入动画库
import gsap from 'gsap'
//导入gui
import * as dat from 'dat.gui'
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将几何体添加到场景中

const gui=new dat.GUI()
gui.add(cube.position,"x").min(0).max(5).step(0.02).name("正方体x坐标").onChange((val)=>{
    
    
    console.log("你修改了x=",val)
}).onFinishChange((val)=>{
    
    
    console.log("完全停下来..",val)
})
//修改物体颜色
let params={
    
    
    color:'#ffff00',
    fn:()=>{
    
    
        gsap.to(cube.rotation,{
    
    x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut"})
    },
}
gui.addColor(params,'color').onChange((val)=>cube.material.color.set(val));
//设置选项卡
gui.add(cube,'visible').name("是否显示");
var folder=gui.addFolder("设置立方体");
folder.add(cube.material,"wireframe");
//设置按钮点击触发某个事件
gui.add(params,"fn").name("立方体运动")
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//设置时钟
// const clock=new $Three.Clock();

//设置动画to(物体的属性,{需要执行的操作..},ease执行方式,repeat:重复的次数(死循环设置-1),yoyo:往返移动,delay:延迟移动,onComplete:()=>完成执行的回调函数,onStart:()=>动画开始执行)
var maveposition=gsap.to(cube.position,{
    
    x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
    
    
    console.log("移动完成")
},
onStart:()=>{
    
    
    console.log("动画开始")
}
});
window.addEventListener('click',()=>{
    
    
    //isActive()表示是否在运行移动
    if(maveposition.isActive()){
    
    
        maveposition.pause();//动画暂停
    }else{
    
    
        maveposition.resume();//动画继续
    }
})
gsap.to(cube.rotation,{
    
    x:2*Math.PI,duration:6,ease: "power1.inOut"})

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});

效果图

在这里插入图片描述

BufferGeometry(设置顶点)

设置顶点创建矩形

BufferGeometry设置顶点创建矩形

/**
 * BufferGeometry设置顶点创建矩形
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//导入动画库
import gsap from 'gsap'
//导入gui
import * as dat from 'dat.gui'
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
const cubeGeometry=new $Three.BufferGeometry();
const vertices=new Float32Array([
    -1.0,-1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0
]);
cubeGeometry.setAttribute("position",new $Three.BufferAttribute(vertices,3));

const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: 0x00ff00});//使用基础材质并设置颜色
//根据几何体和材质创建物体
const mesh=new $Three.Mesh(cubeGeometry,cubeMaterial)

scene.add(mesh)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});

实现三角形

通过循环创建多个角度不同的三角形,要的就是杂乱无章的感觉

/**
 * 使用BufferGeometry实现酷炫三角形
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//导入动画库
import gsap from 'gsap'
//导入gui
import * as dat from 'dat.gui'
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//3、添加物体
//创建几何体
for(let i=0;i<50;i++){
    
    
    const cubeGeometry=new $Three.BufferGeometry();
    const positionArr=new Float32Array(9);
    //3个顶点(每个顶点3个值)
    for(let j=0;j<9;j++){
    
    
        positionArr[j]=Math.random()*5-1;
    }
    cubeGeometry.setAttribute("position",new $Three.BufferAttribute(positionArr,3));
    let color=new $Three.Color(Math.random(),Math.random(),Math.random());//随机颜色
    const cubeMaterial=new $Three.MeshBasicMaterial({
    
    color: color,transparent:true,opacity:0.5});//使用基础材质并设置颜色
    //根据几何体和材质创建物体
    const mesh=new $Three.Mesh(cubeGeometry,cubeMaterial)

    scene.add(mesh)
}


//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});

材质与纹理

  • 通过enableDamping设置阻尼让物体有重量感
  • 代码中演示了纹理的一些常用属性
/**
 * 材质与纹理
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();
//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//导入纹理
const textureloader=new $Three.TextureLoader();
const myTextloader=textureloader.load('../chunyu02.jpg')//加载本地图片

/**
 * 纹理常用的属性
 */
myTextloader.offset.set(0.1,0)//偏移
myTextloader.center.set(0.5,0.5)//旋转的原点
myTextloader.rotation=Math.PI/4//旋转45deg
myTextloader.repeat.set(2,3);//重复
myTextloader.wrapS=$Three.RepeatWrapping;//设置重复模式(该值表示无限重复)
//添加物体
const geometry=new $Three.BoxBufferGeometry(1,1,1);
//材质
const basicMaterial=new $Three.MeshBasicMaterial({
    
    
    color:"#ffff00",
    map:myTextloader
})
const cube=new $Three.Mesh(geometry,basicMaterial);
scene.add(cube)

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});

以上代码主要是对材质与纹理的一个了解使用

标准网格材质

通过MeshStandardMaterial创建标准网格材质

/**
 * 标准网格材质
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中



let event={
    
    }
//单张纹理图的加载
event.onLoad=function(){
    
    
    console.log("加载完成...")
}
event.onProgress=function(e,sum,total){
    
    
    console.log("正在加载的路径",e)
    console.log("加载进度",sum)
    console.log("需要加载的总进度:",total)
    console.log("加载进度百分比:",((sum/total)*100).toFixed(2)+'%');
}
event.onError=function(){
    
    
    console.log("加载失败")
}
//设置加载管理器
const loadingManager=new $Three.LoadingManager(
    event.onLoad,
    event.onProgress,
    event.onError
);
//导入纹理
const textureloader=new $Three.TextureLoader(loadingManager);
const myTextloader=textureloader.load('../chunyu02.jpg')//event.onLoad,event.onProgress,event.onError加载本地图片
/**
 * 纹理常用的属性
 */
myTextloader.offset.set(0.1,0)//偏移
myTextloader.center.set(0.5,0.5)//旋转的原点
myTextloader.rotation=Math.PI/4//旋转45deg
myTextloader.repeat.set(2,3);//重复
myTextloader.wrapS=$Three.RepeatWrapping;//设置重复模式(该值表示无限重复)
//添加物体
const geometry=new $Three.BoxBufferGeometry(1,1,1);
//材质
const material=new $Three.MeshStandardMaterial({
    
    
    color:"#ffff00",
    map:myTextloader,
    roughness:0,//粗糙度
    metalness:0,//金属度
})
//灯光
const light1=new $Three.AmbientLight(0xffffff,0.5);//环境光
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.position.set(10,10,10)//设置平行光照的位置
scene.add(light2)
const cube=new $Three.Mesh(geometry,material);
scene.add(cube)

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});

效果图

在这里插入图片描述

环境贴图

这里我要推荐一个素材网:[Textures - Poliigon](https://www.poliigon.com/textures)

自行去下载hdr图片,这里再推荐个图片格式转换:

[Convertio — 文件转换器](https://www.poliigon.com/textures)

/**
 * 环境贴图
 */
import * as $Three from 'three'
import {
    
    RGBELoader} from 'three/examples/jsm/loaders/RGBELoader'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//加载hdr环境图
const rgbeLoader=new RGBELoader();
rgbeLoader.loadAsync('./public/HdrOutdoorBeachBlueHourCloudy002_HDR_4K.hdr').then(res=>{
    
    
    res.mapping=$Three.EquirectangularReflectionMapping;//设置映射
    scene.background=res;
    scene.environment=res;
})
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中

//设置cube纹理加载器
const cubeTextureloader=new $Three.CubeTextureLoader()
// const envMapTexture=cubeTextureloader.load([
//     "/public/bg1.jpg",
//     "/public/chunyu02.jpg",
//     "/public/bg2.jpg",
//     "/public/chunyu02.jpg",
//     "/public/chunyu02.jpg",
//     "/public/chunyu02.jpg", 
// ]);

const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const textureloader=new $Three.TextureLoader();
const myTextloader=textureloader.load('./public/HdrOutdoorBeachBlueHourCloudy002_JPG_4K.jpg')
const material=new $Three.MeshStandardMaterial({
    
    
    metalness: 0.7,
    roughness: 0.1,
    // envMap:rgbeLoader
    map:myTextloader
})
const sphere=new $Three.Mesh(sphereGeo,material);
scene.add(sphere)
//设置环境背景
// scene.background=envMapTexture;
//设置默认环境背景
// scene.environment=envMapTexture;
//灯光
const light1=new $Three.AmbientLight(0xffffff,0.5);//环境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.position.set(10,10,10)//设置平行光照的位置
scene.add(light2)

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高

//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});
  • 通过loadAsync异步加载hdr环境图
  • 以上代码即可实现身临其境般的感觉

效果图

在这里插入图片描述

还可以360°旋转呢

灯光与阴影

创建一个平面与一个球实现对灯光以及阴影的使用

/**
 * 灯光与阴影
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中


const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//设置球投射阴影
scene.add(sphere)

//创建平面
const planeGeo=new $Three.PlaneBufferGeometry(10,10);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;

plane.receiveShadow=true//接收阴影
scene.add(plane)
//灯光
const light1=new $Three.AmbientLight(0xffffff,0.5);//环境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//设置光线投射阴影
light2.position.set(10,10,10)//设置平行光照的位置
scene.add(light2)

//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高
//开启阴影计算
renderer.shadowMap.enabled=true;
//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});
  • castShadow投射阴影
  • receiveShadow接收阴影
  • renderer.shadowMap.enabled=true;开启阴影计算
  • AmbientLight环境光
  • DirectionalLight平行光

效果图

在这里插入图片描述

平行光的阴影属性

举例一些常见的

/**
 * 平行光阴影属性
 */
light2.shadow.radius=20;//阴影模糊度
light2.shadow.mapSize.set(1080,1080);//阴影贴图分辨率(默认512*512)
//设置平行光投影相机的属性(近端、远端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
scene.add(light2)

聚光灯

通过SpotLight去创建聚光灯

/**
 * 聚光灯
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中


const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//设置球投射阴影
scene.add(sphere)

//创建平面
const planeGeo=new $Three.PlaneBufferGeometry(20,20);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;

plane.receiveShadow=true//接收阴影
scene.add(plane)
//灯光
const light1=new $Three.AmbientLight(0xffffff,0.5);//环境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//设置光线投射阴影
light2.position.set(10,10,10)//设置平行光照的位置
/**
 * 平行光阴影属性
 */
light2.shadow.radius=20;//阴影模糊度
light2.shadow.mapSize.set(1080,1080);//阴影贴图分辨率(默认512*512)
//设置平行光投影相机的属性(近端、远端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
// scene.add(light2)
/**
 * 聚光灯
 */
const light3=new $Three.SpotLight(0xffffff,1);
//调节亮度
light3.intensity=3
light3.position.set(5,5,5);
light3.castShadow=true;
light3.shadow.mapSize.set(1080,1080);
light3.target=sphere;//聚光灯照明目标(设置为球)
sphere.position.x=2//球移动聚光灯追随
light3.angle=Math.PI/6;//聚光灯角度(默认180deg/3)
light3.distance=15;//光的衰减效果
light3.penumbra=0;//伴影的衰减效果
light3.decay=0.1;//沿着光照距离的衰减(需要给渲染器设置)
scene.add(light3)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高
//开启阴影计算
renderer.shadowMap.enabled=true;
renderer.physicallyCorrectLights=true;//使用物理上正确的光照模式
//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//6、使用渲染器,通过相机将场景渲染进来
// renderer.render(scene,camera);

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//编写渲染函数
function render(){
    
    
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});
  • 以上代码并且演示了聚光灯的一些属性

效果图

在这里插入图片描述

点光源

通过PointLight创建

/**
 * 点光源
 */
import * as $Three from 'three'
//导入轨道控制器
import {
    
    OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、创建一个场景
const scene= new $Three.Scene();

//2、创建一个相机
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);

//设置相机位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相机放入场景中


const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//设置球投射阴影
scene.add(sphere)

//创建平面
const planeGeo=new $Three.PlaneBufferGeometry(20,20);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;

plane.receiveShadow=true//接收阴影
scene.add(plane)
//灯光
const light1=new $Three.AmbientLight(0xffffff,0.5);//环境光
scene.add(light1)

/**
 * 添加小球
 */
const smallBall=new $Three.Mesh(
    new $Three.SphereBufferGeometry(0.1,20,20),
    new $Three.MeshBasicMaterial({
    
    color: 0xff0000})
)
smallBall.position.set(2,2,2)
scene.add(smallBall)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//设置光线投射阴影
light2.position.set(10,10,10)//设置平行光照的位置
/**
 * 平行光阴影属性
 */
light2.shadow.radius=20;//阴影模糊度
light2.shadow.mapSize.set(1080,1080);//阴影贴图分辨率(默认512*512)
//设置平行光投影相机的属性(近端、远端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
// scene.add(light2)
/**
 * 点光源
 */
const light4=new $Three.PointLight(0xfff00f,1);
light4.intensity=2;
scene.add(light4)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//设置渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//宽、高
//开启阴影计算
renderer.shadowMap.enabled=true;
renderer.physicallyCorrectLights=true;//使用物理上正确的光照模式
//5、将渲染的内容添加到dom节点中
document.body.appendChild(renderer.domElement)

//创建轨道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//设置控制器阻尼,更有重量感,然后必须在动画循环调用update()
controls.enableDamping=true;

//创建坐标轴
const xy=new $Three.AxesHelper(5);
scene.add(xy);

//设置时钟
const clock=new $Three.Clock();
//编写渲染函数
function render(){
    
    
    let time=clock.getElapsedTime()
    smallBall.position.x=Math.sin(time)*3;
    smallBall.position.z=Math.cos(time)*3;
    smallBall.position.y=2+Math.sin(time*10);
    controls.update();//调用update实现阻尼
    renderer.render(scene,camera);//每一帧就进行一次渲染...
    requestAnimationFrame(render);//浏览器自带方法请求帧
}
render();//调用渲染函数

//监听画面变化,更新画面
window.addEventListener('resize',()=>{
    
    
    //更新摄像头
    camera.aspect=window.innerWidth/window.innerHeight;
    //更新摄像头投影矩阵
    camera.updateProjectionMatrix();
    //更新渲染器
    renderer.setSize(window.innerWidth,window.innerHeight);
    //设置渲染像素比
    renderer.setPixelRatio(window.devicePixelRatio);
});
  • 实现了小球围绕大球转

效果图

在这里插入图片描述

一直转着呢…

了解这些就差不多了,可以去实现一些案例了

猜你喜欢

转载自blog.csdn.net/m_xiaozhilei/article/details/126747505