Three.js-01 入门

这篇博客介绍了Three.js的基本概念,包括Scene、Camera、Geometry和BufferGeometry,以及如何创建物体、使用WebGLRenderer。文章还提到了Material、Mesh、OrbitControls、Clock和requestAnimationFrame,提供了多个示例,如纹理应用和灯光效果,帮助初学者理解Three.js的动画和交互控制。
摘要由CSDN通过智能技术生成

 one

 

 场景(scene)相机(camera), 渲染器(renderer)

Scene-场景

camera-相机

//创建相机
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
);
  • fov — 摄像机视锥体垂直视野角度
  • aspect — 摄像机视锥体长宽比
  • near — 摄像机视锥体近端面
  • far — 摄像机视锥体远端面

  • 这些参数一起定义了摄像机的 viewing frustum(视锥体)

 

透视图中,灰色的部分是视锥体,是可能被渲染的物体所在的区域

fov 是视锥体竖直方向上的张角(是角度制而非弧度制),如侧视图所示。

aspect 等于 width / height,是照相机水平方向和竖直方向长度的比值,通常设为 Canvas 的横纵比例。

near 和 far 分别是照相机到视锥体最近、最远的距离,均为正值,且 fa r应大于 near。

但请注意,不要将 near 和 far 设置为比较极端的数值,如 0.0001 和 99999,这可能引起 bug,让 threejs 无法分辨物体的前后,导致闪动

      Three.js的架构支持多种camera,这里使用最常见的远景相机(PerspectiveCamera),也就是类似于人眼观察的方式。第一个属性75设置的是视角(field of view)

第二个属性设置的是相机拍摄面的长宽比(aspect ratio)

我们几乎总是会使用元素的宽除以高,否则会出现挤压变形。

Geometry-几何

注意:Geometry自从r125版本后已废弃,请使用BufferGeometry。BufferGeometry的性能更好。

缓存几何模型(BufferGeometry)

该类是一个 几何模型(Geometry) 的高效替代,因为它使用缓存(buffer)来保存所有数据,包括顶点位置、面索引、法向量、颜色、UVs以及自定义属性。 这节约了向GPU传递全部这些数据的成本。但同时也使得BufferGeometry要比 几何模型(Geometry) 更难以处理,不是以对象的方式来访问,比如使用Vector3来访问位置数据, 以Color对象来访问颜色数据,你得从相应的attribute缓存中访问原始数据。 这使得BufferGeometry很适合用来存储静态对象,也就是当我们创建完模型实例后不太需要去操作它。

Three.js 中文教程 | 参考手册 | 使用指南 | 动画特效实例 | 踏得网

//创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);

 three自带几何缓冲模型

var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );

 构造器(Constructor)

BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)

width — X轴上的面的宽度 (左右)
height — Y轴上的面的高度 (上下)
depth — Z轴上的面的深度 (前后)
widthSegments — 可选参数. 沿宽度面的分割面数量. 默认值为1.
heightSegments — 可选参数. 沿高度面的分割面数量. 默认值为1.
depthSegments — 可选参数. 沿深度面的分割面数量. 默认值为1.

Material-材质

//材质,颜色
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

 构造器(Constructor)

 MeshBasicMaterial( parameters )

参数是一个使用一个或多个属性定义材料外观的对象。

color — 线条的十六进制颜色。缺省值为 0xffffff。


map — 设置纹理贴图。缺省为null。


aoMap — 设置环境遮挡贴图(ao = ambient occlusion)。缺省为null。


aoMapIntensity — 设置环境遮挡贴图强度。缺省为1。


specularMap — 设置高光贴图。默认为null。


alphaMap — 设置阿尔法贴图。默认为null。

  阿尔法贴图是一个灰度纹理,控制整个表面的不透明度(黑色:完全透明;白色:完全不透明)。默认为空。


envMap — 设置环境贴图。默认为null。


combine — 设置组合操作。默认值是THREE.MultiplyOperation.


reflectivity — 设置反射率。默认值是 1.


refractionRatio — 设置折射率。默认值是 0.98.


fog — 定义材质颜色是否受全局雾设置的影响。默认是true。


shading — 定义着色类型。缺省为 THREE.SmoothShading。


wireframe — 渲染模型为线框。默认是false。


wireframeLinewidth — 线框线宽。默认是1。


wireframeLinecap — 定义线端的外观。默认值是 'round'.


wireframeLinejoin — 定义线连接节点的外观。默认值是 'round'.


vertexColors — 定义顶点如何着色。默认值是 THREE.NoColors.


skinning — 定义材料是否使用皮肤。默认值是false.


morphTargets — 定义材料是否使用 morphTargets。默认值是 false。

 Mesh创建物体

//根据几何体和材质创建物体
const cube = new THREE.Mesh(geometry, material);

WebGLRenderer-渲染器

WebGL渲染器使用WebGL来绘制您的场景,如果您的设备支持的话。使用WebGL将能够利用GPU硬件加速从而提高渲染性能。

//初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
//将webgl渲染的canvas 渲染到body上
document.body.appendChild(renderer.domElement);
//渲染
// renderer.render(scene, camera);

 构造器(Constructor)

WebGLRenderer( parameters )

parameters 是一个可选对象,包含用来定义渲染器行为的属性。当没有设置该参数时,将使用默认值。

canvas — 一个用来绘制输出的 Canvas 对象。
context — 所用的 渲染上下文(RenderingContext) 对象。
precision — 着色器的精度。可以是"highp""mediump" 或 "lowp". 默认为"highp",如果设备支持的话。
alpha — Boolean, 默认为 false.
premultipliedAlpha — Boolean, 默认为 true.
antialias — Boolean, 默认为 false.
stencil — Boolean, 默认为 true.
preserveDrawingBuffer — Boolean, 默认为 false.
depth — Boolean, 默认为 true.
logarithmicDepthBuffer — Boolean, 默认为 false.

.setSize ( width, height, updateStyle )

调整输出canvas尺寸(宽度,高度),要考虑设备像素比,并且设置视口(viewport)以匹配该尺寸。如果设置 updateStyle 为true,则显式添加像素到输出canvas的样式中。

AxesHelper-坐标轴辅助器 

const axesHelper = new THREE.AxesHelper(5);

用于简单模拟3个坐标轴的对象.
红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.

构造函数

AxesHelper( size : Number )

size -- (可选的) 表示代表轴的线段长度. 默认为 1.

OrbitControls-控制器

 three.js docs

const controls = new OrbitControls(camera, renderer.domElement);

Orbit controls(轨道控制器)可以使得相机围绕目标进行轨道运动。
要使用这一功能,就像在/examples(示例)目录中的所有文件一样, 您必须在HTML中包含这个文件。

Clock-时钟

跟踪时间的对象

const clock=new THREE.Clock()

 Three.js 中文教程 | 参考手册 | 使用指南 | 动画特效实例 | 踏得网

requestAnimationFrame --浏览器自带

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

重绘(Repaint)

在浏览器中,重绘指的是改变样式不影响它在文档流中的位置(不影响元素布局,例如,修改颜等..)

重排(回流)(ReFlow)

重排意味着,因为某个元素的布局改变,导致其他元素的位置改变,所以其他元素也要重新绘制

动画为什么会卡?

理想总是很丰满,但现实很残酷。

我们知道,在同一个渲染进程中,存在JS线程GUI线程,JS线程负责执行JS代码,GUI线程负责渲染页面(这里是渲染而不是绘制,绘制由浏览器进程完成)。

因为JS是可以操作DOM的,如果JS线程和GUI线程同时执行,那么渲染线程前后获得的元素可能就不一致了

所以JS执行和页面渲染是互斥的,如果JS执行时间过长,就会导致页面动画卡顿。

试想一下,假如我用js改变某一个DOM元素的高度,我希望每100ms增加1px

let count = 100
setInterval(() => {
    app.style.height = (count++) + 'px'
},100)

有两个问题产生:

  1. JS有可能长时间占据主线程(还有其它事要做),假设JS一直占据500ms,那么就意味着JS操作元素增加10px才渲染新的一帧,那么页面动画看起来就卡卡的,感觉元素在瞬间移动,而不是慢慢过渡
  2. 定时器不准确,导致JS没有在合适的时间内改变元素属性

第一个问题可以通过Web Workers解决,把无关Dom操作的耗时操作放到Web Workers

第二个问题,就可以通过requestAnimationFrame解决

requestAnimationFrame()里面的回调函数不是立即执行,而是绘制的前一时刻由浏览器调用执行,因为实际上requestAnimationFrame是一个宏任务。此外次API专属于浏览器,不能在NodeJs环境运行(Node没有GUI,也就不会有此API)。

和定时器一样,因为调用完了就销毁,所以只调用一次requestAnimationFrame就只执行一次

所以该函数一般来说最多每秒执行60次(如果屏幕刷新率是60HZ)

渲染下一帧就会调用animate函数 类似setTimeout定时器

//---------------------------------浏览器没刷新一帧就执行渲染一次---------------------------------------
function render() {
    //获取时钟运行总时长 获取的单位都是秒
    let time=clock.getElapsedTime()
    //两次获取时间的间隔查,两帧之前的差
  //  let delta=clock.getDelta()
    console.log('获取时钟运行总时长:',time)
    //console.log('两次获取时间(time)间隔:',delta)
    let t = time  % 5
    cube.position.x = t * 1
    renderer.render(scene, camera);
    //--------------------浏览器自带,渲染下一帧就会调用animate函数 类似setTimeout定时器--------------------------------
    //此方法会默认传一个时间参数
    requestAnimationFrame(render);

}
//---------------------------------浏览器没刷新一帧就执行渲染一次---------------------------------------
// function render(time) {
    
//     //console.log(time)
//     //===================时间================= 
//     //利用余数做循环
//     let t = (time / 1000) % 5
//     //------------动画效果 保持均速 路程=速度x时间-----------------
//     cube.position.x = t * 1
//     // if (cube.position.x > 5) {
//     //     cube.position.x = 0
//     // }
//     //---------------旋转动画------------------------------
//     cube.rotation.x += 0.01
//     //------------通过相机将场景渲染进来---------------------
//     renderer.render(scene, camera);
//     //--------------------浏览器自带,渲染下一帧就会调用animate函数 类似setTimeout定时器--------------------------------
//     //此方法会默认传一个时间参数
//     requestAnimationFrame(render);

// }
render();

demo01

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

//创建场景
const scene = new THREE.Scene();
console.log("hello");
console.log(scene);
//创建相机
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
);
//相机位置 xyz坐标
camera.position.set(0, 0, 10);
//相机添加到场景当中
scene.add(camera);
//添加物体到场景
//创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//材质,颜色
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//根据几何体和材质创建物体
const cube = new THREE.Mesh(geometry, material);
//---------------------物体移动 三维向量(Vector3)-------------------------------
//修改物体位置方法
//cube.position.set(5,0,0)
//直接修改属性
cube.position.x = 3
//---------------------------------设置物体缩放-------------------------------
//改变物体形态,x轴变长3倍,y轴2倍,x轴1倍,由正方体变成长方体 x-长,y-高,z-宽
//cube.scale.set(3,2,1)
//cube.scale.x=5
//-------------------rotation 旋转------------------------------------
//Math.PI=180度,最后一个参数旋转顺序
cube.rotation.set(Math.PI / 4, 0, 0, "XZY")

//添加场景当中
scene.add(cube);
//初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
//将webgl渲染的canvas 渲染到body上
document.body.appendChild(renderer.domElement);
//------------------------------------------使用渲染器,通过相机将场景渲染进来---------------------------
//renderer.render(scene,camera);

//--------------------------------------添加坐标轴辅助器----------------------------------
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

//----------------------------创建轨道控制器,相机围绕物体转动----------------------------------------
const controls = new OrbitControls(camera, renderer.domElement);


//使用three.js的clock时钟处理动画
const clock=new THREE.Clock()

//---------------------------------浏览器没刷新一帧就执行渲染一次---------------------------------------
function render() {
    //获取时钟运行总时长 获取的单位都是秒
    let time=clock.getElapsedTime()
    //两次获取时间的间隔查,两帧之前的差
  //  let delta=clock.getDelta()
    console.log('获取时钟运行总时长:',time)
    //console.log('两次获取时间(time)间隔:',delta)
    let t = time  % 5
    cube.position.x = t * 1
    renderer.render(scene, camera);
    //--------------------浏览器自带,渲染下一帧就会调用animate函数 类似setTimeout定时器--------------------------------
    //此方法会默认传一个时间参数
    requestAnimationFrame(render);

}
//---------------------------------浏览器没刷新一帧就执行渲染一次---------------------------------------
// function render(time) {
    
//     //console.log(time)
//     //===================时间================= 
//     //利用余数做循环
//     let t = (time / 1000) % 5
//     //------------动画效果 保持均速 路程=速度x时间-----------------
//     cube.position.x = t * 1
//     // if (cube.position.x > 5) {
//     //     cube.position.x = 0
//     // }
//     //---------------旋转动画------------------------------
//     cube.rotation.x += 0.01
//     //------------通过相机将场景渲染进来---------------------
//     renderer.render(scene, camera);
//     //--------------------浏览器自带,渲染下一帧就会调用animate函数 类似setTimeout定时器--------------------------------
//     //此方法会默认传一个时间参数
//     requestAnimationFrame(render);

// }
render();

Demo2 使用gsap动画库

TweenMax使用方法_TweenMax中文网

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//导入动画库gsap
import gsap from 'gsap'

//创建场景
const scene = new THREE.Scene();

//创建相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
//相机位置 xyz坐标
camera.position.set(0, 0, 10);
//相机添加到场景当中
scene.add(camera);
//添加物体到场景
//创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//材质,颜色
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//根据几何体和材质创建物体
const cube = new THREE.Mesh(geometry, material);
//---------------------物体移动 三维向量(Vector3)-------------------------------
//修改物体位置方法
//cube.position.set(5,0,0)


//---------------------------------设置物体缩放-------------------------------
//改变物体形态,x轴变长3倍,y轴2倍,x轴1倍,由正方体变成长方体 x-长,y-高,z-宽
//cube.scale.set(3,2,1)
//cube.scale.x=5
//-------------------rotation 旋转------------------------------------
//Math.PI=180度,最后一个参数旋转顺序
cube.rotation.set(Math.PI / 4, 0, 0, "XZY")

//添加场景当中
scene.add(cube);
//初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
//将webgl渲染的canvas 渲染到body上
document.body.appendChild(renderer.domElement);
//------------------------------------------使用渲染器,通过相机将场景渲染进来---------------------------
//renderer.render(scene,camera);

//--------------------------------------添加坐标轴辅助器----------------------------------
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

//----------------------------创建轨道控制器,相机围绕物体转动----------------------------------------
const controls = new OrbitControls(camera, renderer.domElement);
//=================设置控制器阻尼(惯性),让控制器有更真实的效果, 必须在动画循环调用.update()==========
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yzhSWJ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值