ThreeJS入门

简介

Three.js是一个基于原生WebGL,轻量级,跨平台的Javascript库,可以在浏览器上结合HTML5的canvas,SVG或者WebGL,创建和展示3D模型和动画。允许我们在不依赖任何浏览器插件的情况下,创建一个GPU加速的3D动画场景。

WebGL是一种JavaScript API,用于在不使用插件的情况下在任何兼容的网页浏览器中呈现交互式2D和3D图形。WebGL完全集成到浏览器的所有网页标准中,可将影像处理和效果的GPU加速使用方式当做网页Canvas的一部分。WebGL元素可以加入其他HTML元素之中并与网页或网页背景的其他部分混合,WebGL技术结合了HTML5和 Java Script,允许开发者在网页(Web页面)上创建和渲染三维图形。

WebGL 工作原理

WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点。

左侧是你提供的数据。顶点着色器(Vertex Shader)是写进GLSL中的一个方法,每个顶点调用一次,在这个方法中做一些数学运算后设置了一个特殊的gl_Position变量, 这个变量就是该顶点转换到裁剪空间中的坐标值,GPU接收该值并将其保存起来。

假设你正在画三角形,顶点着色器每完成三次顶点处理,WebGL就会用这三个顶点画一个三角形。 它计算出这三个顶点对应的像素后,就会光栅化这个三角形。对于每一个像素,它会调用片段着色器询问你使用什么颜色。 你通过给片段着色器的一个特殊变量gl_FragColor设置一个颜色值,实现自定义像素颜色。

基本概念

ThreeJS 采用的是右手坐标系。

场景Scene

Scene对象可以理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,所有物品的容器。可以把场景想象成一个空房间,接下来会往房间里面放置要呈现的物体、相机、光源。

// 创建3D场景对象Scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);

物体形状:几何体Geometry

形状决定物体的轮廓

//BoxGeometry:长方体 参数1: x 参数2: y 参数3: z
const geometry = new THREE.BoxGeometry(100, 100, 100);
// SphereGeometry:球体
const geometry = new THREE.SphereGeometry(50);
// CylinderGeometry:圆柱 参数1: 顶部半径 参数2: 底部半径 参数3: 高
const geometry = new THREE.CylinderGeometry(50,50,100);
// PlaneGeometry:矩形平面
const geometry = new THREE.PlaneGeometry(100,50);
// CircleGeometry:圆形平面
const geometry = new THREE.CircleGeometry(50);

物体外观:材质Material

材质则是物体的材料和质感,如果你想定义物体的外观效果,比如颜色,就需要通过材质Material实现。

//创建一个材质对象Material, 参数: 用于定义材质外观的对象
const material = new THREE.MeshBasicMaterial({
    color: 0x000000,//设置材质颜色为黑色
    transparent:true,//开启透明
    opacity:0.5,//设置透明度
}); 

物体:网格模型Mesh

实际生活中有各种各样的物体,在threejs中可以通过网格模型Mesh表示一个虚拟的物体。物体由形状和材质两部分组成。

// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material);
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(0,10,0);
//通过add方法把网格模型Mesh添加到场景Scene
scene.add(mesh); 

相机Camera

如果想把三维场景Scene渲染到web网页上,还需要定义一个虚拟相机Camera

Threejs 必须要往场景中添加一个相机,用来确定观察位置、方向、角度,相机看到的内容,就是我们最终在屏幕上看到的内容。

Threejs提供了正交相机OrthographicCamera和透视相机PerspectiveCamera。

透视投影跟人眼看到的世界是一样的,近大远小;正交投影则远近都是一样的大小。

// 实例化一个透视投影相机对象
// fov — 相机视锥体垂直视野角度
// aspect — 相机视锥体长宽比
// near — 相机视锥体近端面
// far — 相机视锥体远端面
const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
//通过position属性设置相机在坐标系中的位置
camera.position.set(200, 200, 200); 
//通过lookAt设置相机观察目标指向3D空间中某个位置
camera.lookAt(0, 0, 0);

渲染器

Threejs 绘制的东西,最终需要在屏幕一块画布上显示出来。

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 定义输出的Canvas画布尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 场景Scene渲染在canvas上
renderer.render(scene, camera); //执行渲染操作
// Canvas插入到任意HTML元素中
document.body.appendChild(renderer.domElement);

光源对物体表面影响

实际生活中物体表面的明暗效果是会受到光照的影响,比如晚上不开灯,你就看不到物体,灯光比较暗,物体也比较暗。在threejs中,用网格模型Mesh模拟生活中物体,所以threejs中模拟光照Light对物体表面的影响,就是模拟光照Light对网格模型Mesh表面的影响。

基础网格材质MeshBasicMaterial不会受到光照影响。漫反射网格材质MeshLambertMaterial会受到光照影响。

一个立方体使用漫反射网格材质MeshLambertMaterial,不同面和光线夹角不同,立方体不同面就会呈现出来不同的明暗效果。

光源Light

假如没有光,摄像机看不到任何东西,因此需要往场景中添加光源。为了跟真实世界更加接近,Threejs 支持模拟不同光源,展现不同光照效果,有点光源、平行光、聚光灯、环境光等。

点光源
//点光源:两个参数分别表示光源颜色和光照强度
// 参数1:光源颜色
// 参数2:光照强度
const pointLight = new THREE.PointLight(0xffffff, 1.0);
// 或者通过intensity设置光照强度
pointLight.intensity = 1.0;
光源衰减

随着距离的改变,光线会衰减,越来越弱,光源衰减属性decay默认值是2.0。

pointLight.decay = 0.0;//设置光源不随距离衰减
光源位置

把点光源想象为一个灯泡,在3D空间中,放的位置不同,模型的渲染效果就不一样。

//点光源位置
pointLight.position.set(400, 0, 0);
scene.add(pointLight); //点光源添加到场景中
点光源辅助观察PointLightHelper

通过点光源辅助观察对象PointLightHelper可视化点光源。

// 光源辅助观察
// 参数1:被模拟的光源.
// 参数2:尺寸. 默认为 1.
// 参数3:颜色,如果没有设置颜色将使用光源的颜色.
const pointLightHelper = new THREE.PointLightHelper(pointLight, 10, 0xff0000);
scene.add(pointLightHelper);
环境光

环境光AmbientLight没有特定方向,只是整体改变场景的光照明暗。

const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);
平行光

平行光DirectionalLight就是沿着特定方向发射。亮度与光源和物体之间的距离无关,只与平行光的角度和物体所在平面有关。

// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(80, 100, 50);
// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);
平行光辅助观察DirectionalLightHelper
// DirectionalLightHelper:可视化平行光
// 参数1:被模拟的光源.
// 参数2:尺寸. 默认为 1.
// 参数3:颜色,如果没有设置颜色将使用光源的颜色.
const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5,0xff0000);
scene.add(dirLightHelper);
聚光源

聚光源可以认为是一个沿着特定方会逐渐发散的光源,照射范围在三维空间中构成一个圆锥体。

// 聚光源
const spotLight = new THREE.SpotLight(0xffffff,1.0);
// 设置聚光光源位置
spotLight.position.set(100, 100, 100);
// 设置聚光光源发散角度
spotLight.angle = Math.PI / 6;//光锥角度的二分之一
scene.add(spotLight);//光源添加到场景中
// spotLight.target是一个模型对象Object3D,默认在坐标原点
spotLight.target.position.set(50,0,0);
//spotLight.target添加到场景中.target.position才会起作用
scene.add(spotLight.target);
聚光源辅助对象SpotLightHelper
// 聚广源辅助对象,可视化聚广源
const spotLightHelper = new THREE.SpotLightHelper(spotLight,0xffffff)
scene.add(spotLightHelper);

辅助观察坐标系

THREE.AxesHelper()的参数表示坐标系坐标轴线段尺寸大小,可以根据需要改变尺寸。

// 辅助观察的坐标系
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

相机控件OrbitControls

开发调试代码,或者展示模型的时候,可以通过相机控件OrbitControls实现旋转缩放预览效果。

// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
controls.addEventListener('change', function () {
    renderer.render(scene, camera); //执行渲染操作
});

动画渲染循环

threejs可以借助HTML5的API请求动画帧window.requestAnimationFrame实现动画渲染。

// 渲染函数
function animate() {
    renderer.render(scene, camera); //执行渲染操作
    mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
    mesh.rotateX(0.01)
    mesh.scale.x = 2; //延X方向放大
    mesh.position.y += 0.1 * i; //延y轴移动
    requestAnimationFrame(animate);//请求再次执行渲染函数render,渲染下一帧
}
animate();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值