threejs基本使用

118 阅读5分钟

第一个3d案例

import * as THREE from "three";
// 创建场景
const scene = new THREE.Scene();
// 创建几何对象
const geometry = new THREE.BoxGeometry(); 
// 创建材质对象
const material = new THREE.MeshBasicMaterial({color:"yellow",transparent:true,opacity:0.5});
// 创建虚拟物体
const mesh = new THREE.Mesh(geometry,material);
// 设置物体的位置,默认原点 上升十个单位
mesh.position.set(10,10,0);
// 将虚拟物体添加到场景中
scene.add(mesh);

// 创建辅助观察坐标系 参数:坐标系坐标轴线段尺寸大小
// 红色x 绿色y 蓝色z
const axesHelper = new THREE.AxesHelper(10);
// 添加到场景中
scene.add(axesHelper);

// 定义相机输出的画布大小
const width = 800;
const height = 800;
// 创建相机对象(透视投影相机),可以传入0个或多个参数
/**
 * - fov:视锥体竖直方向视野角度,默认50
 * - aspect:视锥体水平方向跟竖直方向的长度比,一般是width/height,默认1
 * - near:视锥体近截面相对于相机的距离,默认0.1
 * - far:视锥体远截面相对于相机的距离,默认2000
 */
const camera = new THREE.PerspectiveCamera();
// 设置相机位置
camera.position.set(10, 30, 10);
// 设置观察目标,可以传入一个三维坐标
camera.lookAt(mesh.position); //这里使用虚拟物体的坐标

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 设置画布大小
renderer.setSize(width,height);
// 执行渲染方法
renderer.render(scene,camera);
// 将canvas插入到页面
onMounted(()=>{
  document.querySelector("#container").appendChild(renderer.domElement);
})

光照

threejs中的材质,有的受光照影响,有的则不受影响

  • 不受光照影响:MeshBasicMaterial
  • 受光照影响:
    • 漫反射:MeshLambertMaterial
    • 高光:MeshPhongMaterial
    • 物理:
      • MeshStandardMaterial
      • MeshPhysicalMaterial 光源分为:
  • 环境光:AmbientLight
  • 点光源:PointLight
  • 聚光灯光源:SpotLight
  • 平行光:DirectionalLight
// 创建材质对象
const material = new THREE.MeshLambertMaterial();
// 创建点光源对象, 光照颜色 光照强度,如果不生效就添加参数3 4且都为0或者版本回退到155之前
const pointLight = new THREE.PointLight("red",1.0);
// 设置位置
pointLight.position.set(10,20,0);
// 添加到场景中才能生效
scene.add(pointLight)

相机控件OrbitControls

// 引入轨道控制器
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

const controls = new OrbitControls(camera,renderer.domElement);
controls.addEventListener("change",()=>{
  renderer.render(scene,camera); //如果有动画渲染函数就不用调用渲染了
})

  // 添加阻尼
  controls.enableDamping = true;
  controls.dampingFactor = 0.01;

  // 自动旋转 想要使用自动旋转必须在动画渲染函数中调用controls.update()
  controls.autoRotate = true
  controls.autoRotateSpeed = 2; //默认2,数值越小,旋转越快

还可以监听start,end事件
控件本质上是修改了相机的参数
左键旋转 右键平移 滚轮缩放

平行光与环境光

// 创建点光源辅助观察对象可视化点光源
const pointLightHelper = new THREE.PointLightHelper(pointLight);
// 添加到场景中显示
scene.add(pointLightHelper);

// 环境光没有特定的方向,只能整体改变场景的光照明暗
const ambient = new THREE.AmbientLight("#ffffff",0.2);
// 添加到场景中
scene.add(ambient)

// 平行光就是沿着特定方向发射
const directional = new THREE.DirectionalLight("#ffffff",1)
// 设置光源方向,通过光源的postion和目标指向对象的position属性计算
directional.position.set(20,20,20);
// 设置指向的模型,默认原点
directional.target = mesh;
scene.add(directional);

// 平行光辅助观察, 2 3:辅助观察的大小以及颜色
const directionalHelper = new THREE.DirectionalLightHelper(directional,1,"red");
// 添加到场景中显示
scene.add(directionalHelper)

动画循环渲染

const render = () => {
  requestAnimationFrame(render);
  mesh.rotateY(0.01)
  // 执行渲染方法
  renderer.render(scene,camera);
}

借助js api的requestAnimationFrame实现,每一帧都重新渲染

完整代码

import { onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

// 创建场景
const scene = new THREE.Scene();
// 创建几何对象
const geometry = new THREE.BoxGeometry(); 
// 创建材质对象
const material = new THREE.MeshLambertMaterial();
// 创建虚拟物体
const mesh = new THREE.Mesh(geometry,material);
// 设置物体的位置,默认原点 上升十个单位
mesh.position.set(10,10,0);
// 将虚拟物体添加到场景中
scene.add(mesh);

// 创建点光源对象, 光照颜色 光照强度
// const pointLight = new THREE.PointLight("#ffffff",1.0,0,0)
// 设置位置
// pointLight.position.set(10,20,20);
// 添加到场景中才能生效
// scene.add(pointLight);
// 环境光没有特定的方向,只能整体改变场景的光照明暗
// const ambient = new THREE.AmbientLight("#ffffff",0.2);
// 添加到场景中
// scene.add(ambient)
// 平行光就是沿着特定方向发射
const directional = new THREE.DirectionalLight("#ffffff",1)
// 设置光源方向,通过光源的postion和目标指向对象的position属性计算
directional.position.set(20,20,20);
// 设置指向的模型,默认原点
directional.target = mesh;
scene.add(directional);

// 平行光辅助观察, 2 3:辅助观察的大小以及颜色
const directionalHelper = new THREE.DirectionalLightHelper(directional,1,"red");
// 添加到场景中显示
scene.add(directionalHelper)

// 创建点光源辅助观察对象可视化点光源
// const pointLightHelper = new THREE.PointLightHelper(pointLight);
// 添加到场景中显示
// scene.add(pointLightHelper)

// 创建辅助观察坐标系 参数:坐标系坐标轴线段尺寸大小
// 红色x 绿色y 蓝色z
const axesHelper = new THREE.AxesHelper(10);
// 添加到场景中
scene.add(axesHelper);

// 定义相机输出的画布大小
const width = 800;
const height = 800;
// 创建相机对象(透视投影相机),可以传入0个或多个参数
/**
 * - fov:视锥体竖直方向视野角度,默认50
 * - aspect:视锥体水平方向跟竖直方向的长度比,一般是width/height,默认1
 * - near:视锥体近截面相对于相机的距离,默认0.1
 * - far:视锥体远截面相对于相机的距离,默认2000
 */
const camera = new THREE.PerspectiveCamera();
// 设置相机位置
camera.position.set(10, 30, 10);
// 设置观察目标,可以传入一个三维坐标
camera.lookAt(mesh.position); //这里使用虚拟物体的坐标

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();
// 设置画布大小
renderer.setSize(width,height);

// 创建轨道控制器对象
const controls = new OrbitControls(camera,renderer.domElement);
controls.addEventListener("change",()=>{
  // renderer.render(scene,camera)
})

  // 添加阻尼
  controls.enableDamping = true;
  controls.dampingFactor = 0.01;

  // 自动旋转
  controls.autoRotate = true
  controls.autoRotateSpeed = 2

const render = () => {
  requestAnimationFrame(render);
  mesh.rotateY(0.01);
  controls.update()
  // 执行渲染方法
  renderer.render(scene,camera);
}

// 将canvas插入到页面
onMounted(()=>{
  document.querySelector("#container").appendChild(renderer.domElement);
  render();
})