Three入门学习笔记整理
Three入门学习笔记整理
一、官方网站:https://threejs.org
二、关于Three.js
WebGL是大部分浏览器直接支持的一种3D绘图标准,它可以创建二维图形和应用,还可以充分利用GPU,创建漂亮的、高性能的三维应用。直接使用WebGL非常复杂,Three.js库提供了一套基于WebGL的、非常易用的JavaScrip API,它源自github的一个开源项目,通过这些API可以直接在浏览器中创建三维场景。本文整理了一些入门资料。
三、开始
- 引入
可以直接在HTML引入Three.js:
<script src="three.js"></script>
也可以用npm安装:
npm i three
import * as THREE from 'three'
- 使用
three渲染一个3D场景需要以下必要元素:
1.场景(Scene):是物体、光源等元素的容器,要渲染的东西需要先添加进场景;
2.相机(Camera):控制视角的位置、范围以及视觉焦点的位置,一个3D环境中只能存在一个相机;
3.光源(Light):包括全局光、平行光、点光源;
4.物体对象(Mesh):包括二维物体(点、线、面)、三维物体、粒子等;
5.渲染器(Renderer):指定渲染方式,如webGL\canvas2D\Css2D\Css3D等;
非必要元素:
控制器(Control):相机控件,可通过键盘、鼠标控制相机的移动。
四、实例
基本结构
const width = window.innerWidth;
const height = window.innerHeight;
var renderer;
var camera;
var light;
var scene;
function initRender() {
// 初始化渲染器
renderer = new THREE.WebGLRenderer({
antialias: true// 抗锯齿
});
renderer.setSize(width, height); // 设置大小
renderer.setClearColor(0xffffff, 1.0); // 设置背景色
document.body.appendChild(renderer.domElement);
}
function initScene() {
// 初始化场景
scene = new THREE.Scene();
}
function initCamera() {
// 初始化相机
camera = new THREE.PerspectiveCamera(45, width / height, 10, 10000); // 添加透视相机
camera.position.set(500, 500, 500); // 设置相机位置
camera.up.set(0, 1, 0); // 相机以哪个轴为上方
camera.lookAt(0, 0, 0); // 相机焦点设置
}
function initLight() {
// 初始化灯光
light = new THREE.DirectionalLight({ color: 0xffffff }); // 添加平行光
light.position.set(1, 0, 0); // 光的方向(x,y,z)
scene.add(light);
let pointLight = new THREE.PointLight(0xffffff); // 添加点光源
pointLight.position.set(100, 100, 100); // 点光源的位置
scene.add(pointLight);
let pointHelper = new THREE.PointLightHelper(pointLight, 5, 0xff0000); // 设置点光源辅助工具,可以看到点光源的位置
scene.add(pointHelper);
}
function initObject() {
// 初始化物体
let geometry = new THREE.CylinderGeometry(100, 100, 300, 100, 100); // 添加一个圆柱体
let material = new THREE.MeshLambertMaterial({
color: 0xffff00
}); // 添加材料
// material.wireframe=true; // 圆柱体是否以网格显示
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, 0);
scene.add(mesh);
}
function initAxes() {
// 添加辅助坐标轴
let axes = new THREE.AxesHelper(1000);// 蓝色为Z轴,绿色为Y轴,红色为X轴
scene.add(axes);
}
function threeStart() {
initRender();
initScene();
initCamera();
initLight();
initAxes();
initObject();
renderer.clear();
renderer.render(scene, camera);
}
window.onload = function () {
threeStart();
};
结果
五、概念
坐标系
three.js中采用的是右手坐标系,坐标轴方向主要是camera.up.set(x, y, z);
设置。也就是说在相机眼里(其实就是我们看的角度)哪个轴向上。理解坐标系很重要,详情请看three右手坐标系讲解。
场景
物体、光源、控制器的添加必须使用secen.add(object)添加到场景中才能渲染出来。
var scene;
function initScene(){
scene=new THREE.Scene();
}
相机
正交投影相机:
THREE.OrthographicCamera(left, right, top, bottom, near, far) // 大小不因远近而变化
透视投影相机:
THREE.PerspectiveCamera(fov, aspect, near, far) // 遵循近大远小的空间规则
一般情况下,我们使用的是透视投影相机,其参数为:
fov:垂直方向夹角(视角)
aspect:可视区域长宽比 width/height
near:渲染区域离摄像机最近的距离
far:渲染区域离摄像机最远的距离,仅在距离摄像机near和far间的区域会被渲染到canvas中
相机的位置设置:
camera.position.set(x,y,z)或camera.position = new THREE.Vector3(x, y, z);
控制相机的焦点位置,决定相机的朝向
camera.lookAt(0, 0, 0);
添加相机辅助工具来查看相机的位置
灯光
全局光:THREE.AmbientLight,影响整个scene的光源,一般是为了弱化阴影或调整整体色调,可设置光照颜色,以颜色的明度确定光源亮度;
平行光:THREE.DirectionalLight,模拟类似太阳的光源,所有被照射的区域亮度是一致的,可设置光照颜色、光照方向(通过向量确定方向),以颜色的明度确定光源亮度;
点光源:THREE.PointLight,单点发光,照射所有方向,可设置光照强度,光照半径和光颜色;
聚光灯:THREE.SpotLight,这种光源有聚光的效果,类似于台灯,吊灯,手电筒。
最简单的用法:
function initLight() {
light = new THREE.DirectionalLight({ color: 0xffffff }); // 创建白色平行光
light.position.set(1, 0, 0); // 平行光只需设置方向向量,其他光源需要设置具体位置
scene.add(light);
}
光影关系可以显著影响显示效果。参考资料:https://www.cnblogs.com/amy2011/p/5761174.html
3D模型
我们可以用three自由地创建一些点、线、面和几何体。或者加载一些已经做好的3D模型,three更新的很快,目前支持大部分格式的3D模型,以后会越来越多。
function initObject() {
// 添加一个圆柱体
let geometry = new THREE.CylinderGeometry(100, 100, 300, 100, 100);
let material = new THREE.MeshLambertMaterial({ color: 0xffff00 });
mesh = new THREE.Mesh(geometry, material);
mesh.position = new THREE.Vector3(0, 0, 0);
scene.add(mesh);
}
CylinderGeometry是柱体,控制底面边的数量可以得到近似的圆柱体,还可以创建正方体、球、环、文字等已经设定好的几何体。如果库里没有需要的,可以自己创建自定义几何体。
function initCar() {
// 加载一个外部.obj汽车模型
let mtlLoader = new THREE.MTLLoader();
mtlLoader.load('../../../3Dmodel/Lamborghini/Avent.mtl', (materials) => {
// 加载材料
materials.preload();
let objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load('../../../3Dmodel/Lamborghini/Avent.obj', (object) => {// 加载模型
object.scale.set(80, 80, 80); // 放大倍数
scene.add(object);
}, (suc) => { console.log(((suc.loaded / suc.total) * 100) + '% OBJloaded'); }, (err) => { console.log(err); }
);
}, (suc) => { console.log(((suc.loaded / suc.total) * 100) + '% MTLloaded'); }, (err) => { console.log(err); });
}
three.js加载外部文件需要用“loader系列”方法,通过这些方法可以加载.obj、.json、.dae等格式的模型(点击查看不同格式的模型之间的差异及优劣)。
像这种将一张图片当作一个平面的,要用Texture加载材质(纹理)。参考资料
六、简单动画
动画
动画有两种方式,一种是让图像动,另一种是让相机动。
一个简单的旋转:function animate() {
var v1 = new THREE.Vector3( 1, 1, 1 );
meshAll.rotateOnAxis(v1,0.01);
mesh.rotation.z -= 0.01;
requestAnimationFrame(animate);
renderer.render(scene,camera);
stats.update();
}
性能检测
为了监控帧率,引用Stats插件来监控动画的帧率
<script src="Stats.js"></script>
……
function initStats() {
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.left = '0px';
document.body.appendChild(stats.domElement);
}
七、交互控制
dat.gui
资料:https://www.cnblogs.com/xiaoniuzai/p/6685556.html其它插件
three自己也提供了很多插件来控制,例如OrbitControls,详情请看官网!
function initControl() {
controls = new THREE.OrbitControls(camera);
// controls.enabled = false;// boolean,禁用控制器
// controls.enableKeys = false; // boolean,禁用键盘
// controls.autoRotate = true; // boolean,是否自动旋转,所有的旋转都是绕着场景中心旋转,不是原点
// controls.autoRotateSpeed = 2; // Number,自动旋转速度
controls.enableDamping = true; // boolean, 开启后有缓冲效果,具有物理的阻力感
controls.dampingFactor = 0.3; // Float, 阻尼系数(0~1),数值越低,阻力越小
// controls.enablePan = false; // boolean,禁止平移
// controls..panSpeed = 0.5; // 平移速度
// controls.enableRotate = false; // boolean,禁止旋转
// controls.enableZoom = false; // boolean,禁止远近拉伸
// controls.zoomSpeed = 0.1;// 鼠标滚动一个单位时拉伸幅度
// controls.rotateSpeed = 0.5;// 旋转速度
// controls.keyPanSpeed = 0.5; // Float, 用键盘平移的速度
// controls.keys = {
// LEFT: 65,
// RIGHT: 68,
// UP: 87,
// BOTTOM: 83
// }; // 键盘编码
// controls.minAzimuthAngle = 0 * Math.PI; // 水平方向最小角度
// controls.maxAzimuthAngle = 0.5 * Math.PI; // 水平方向最大角度,当Z轴向上时,从Z轴正方向往下看,逆时针90度
// controls.minDistance = 500; // 相机离物体最近距离
// controls.maxDistance = 600; // 相机离物体最远距离
// controls.minPolarAngle = 0 * Math.PI;// 上下两极的可视区域最小角度
// controls.maxPolarAngle = 0.5 * Math.PI;// 上下两极的可视区域最大角度,Z轴向上,从屏幕正上方往下90度
// controls.mouseButtons = {
// ORBIT: THREE.MOUSE.LEFT,
// ZOOM: THREE.MOUSE.MIDDLE,
// PAN: THREE.MOUSE.RIGHT
// }; // 鼠标键位设置
// controls.screenSpacePanning = false; // boolean,false时只能在不是向上轴的方向移动。比如相机Z轴向上,那么物体只能在XY平面内移动
// controls.target = new THREE.Vector3(300, 200, 0); // 相机聚焦坐标
}
结束
一个练习demo:一个采用 Three.js 的 3D 动画场景制作:飞行者
这些只是入门资料整理,如果想做出官网展示的那些demo,还要自己下功夫钻研!让我们一起快乐地学习吧!
Three入门学习笔记整理的更多相关文章
- React 入门学习笔记整理目录
React 入门学习笔记整理(一)--搭建环境 React 入门学习笔记整理(二)-- JSX简介与语法 React 入门学习笔记整理(三)-- 组件 React 入门学习笔记整理(四)-- 事件 R ...
- node.js入门学习笔记整理
(1)node Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node与javaScript的区别在于,javaScript的顶层对象是window,而no ...
- React 入门学习笔记整理(一)——搭建环境
使用create-react-app脚手架搭建环境 1.安装node .软件下载地址:https://nodejs.org/en/,我下的推荐的版本. 安装之后测试是否安装成功.windows系统下, ...
- React 入门学习笔记整理(二)—— JSX简介与语法
先看下这段代码: import React from 'react'; //最终渲染需要调用ReactDOM库,将jsx渲染都页面中 import ReactDOM from 'react-dom'; ...
- React 入门学习笔记整理(三)—— 组件
1.定义组件 1)函数组件 function GreateH(props){ return <div> <h2>hello,{props.name}</h2> &l ...
- React 入门学习笔记整理(四)—— 事件
1.事件定义 React事件绑定属性的命名采用驼峰式写法,而不是小写. 如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法) 在类组件中定义函数,通过thi ...
- React 入门学习笔记整理(五)—— state
1.state 1)组件本省也是有状态的,定义在组件内部的state中,state的状态只能由组件自身改变,任何其他组件都不能改变. 当需要改变state时,通过调用setState方法来改变,set ...
- React 入门学习笔记整理(六)—— 组件通信
1.父子组件通信 1)父组件与子组件通信,使用Props 父组件将name传递给子组件 <GreateH name="kitty"/> 子组件通过props接收父组件的 ...
- React 入门学习笔记整理(七)—— 生命周期
(1)react 生命周期 只有类组件有生命周期,函数组件没有生命周期 1.挂载阶段:这些方法会在组件实例被创建和插入DOM中时被调用: 1)constructor(props) 初始化组件的状态.绑 ...
随机推荐
- (转)Arcgis for JS实现台风运动路径与影像范围的显示
http://blog.csdn.net/gisshixisheng/article/details/42025435 首先,看看具体的效果: 初始化状态 绘制中 绘制完成 首先,组织数据.我组织的数 ...
- WPF动态折线图
此项目源码下载地址:https://github.com/lizhiqiang0204/WpfDynamicChart 效果图如下: 此项目把折线图制作成了一个控件,在主界面设置好参数直接调用即可,下 ...
- Jquery向页面append新元素之后,如何解决事件的绑定问题?
今天有get到一个新知识点,就是当我们向页面添加新的元素之后,加载之前的函数方法就对新元素失效了,下面我来说说如何解决这个问题的? 我先看jq api文档没有找到方法,无果只好到网上找些资料,果然找到 ...
- Monkey基本常用命令整理
adb shell monkey -v 500 >F:/monkeylog2018.txt -P表示包名 -V表示输出日志的详细级别 一个-V表示一级 递增 >输出日志 ...
- [Ynoi2016]镜中的昆虫
题目大意: 给定一个序列,有2个操作: 1. 区间覆盖.2. 区间数颜色. 解题思路: 珂朵莉树+树套树. 看到区间覆盖当然想到珂朵莉树然而这是Ynoi 所以我们得优化掉珂朵莉树那个暴力过程. 考虑对 ...
- Golang - 复合类型
目录 Golang - 复合类型 1. 指针 2. new()和make() 3. 数组 4. slice 5. Map 6. 结构体 7. 结构体参数 Golang - 复合类型 1. 指针 go语 ...
- 2.1 SVN的安装
一.SVN客户端安装 运行TortoiseSVN-1.6.6.17493-win32-svn-1.6.6.msi程序, 开始安装 点击Next, 下一步 选择 I accept 接受, 点击Next ...
- c# 数组 字符串 C#中判断字符串中包含某个字符
string str = "1,2,3,4,5,6,7"; string[] strArray = str.Split(','); //字符串转数组 ...
- 听说”双11”是这么解决线上bug的
听说"双11"是这么解决线上bug的 --Android线上热修复的使用与原理 预备知识和开发环境 Android NDK编程 AndFix浅析 Android线上热修复的原理大同 ...
- 基于DPI(深度报文解析)的应用识别2------实际分析
新浪微博的分析 早上刚刚起床先刷微博,打算就分析一下新浪微博.登陆之后抓取公布微博的数据包.进行分析. 1.抓包的要点: 1.关闭其它网络应用,保证本机网络流量的干净,便于分析. 2.先开启wires ...