three.js的基本使用

457 阅读3分钟

基本使用

初始化场景

const scene = new THREE.Scene();

初始化相机

相当于人眼

const camera = new THREE.PerspectiveCamera();

camera.position.set( 0, 20, 100 );

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

fov — 摄像机视锥体垂直视野角度
aspect — 摄像机视锥体长宽比
near — 摄像机视锥体近端面
far — 摄像机视锥体远端面

设置相机位置

camera.position.z = 0.1;

设置渲染器

const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);

时刻渲染

const renderFn = () => {
  renderer.render(scene, camera);
  requestAnimationFrame(renderFn);
};

放入dom

const container = ref(null);

container.value.appendChild(renderer.domElement);

控制器

// 添加控制器 const controls = new OrbitControls(camera, container.value); controls.enableDamping = true;

通常在元素挂载时,放入控制器,时刻渲染,放入dom

坐标轴

const axesHelper = new THREE.AxesHelper(5);

scene.add(axesHelper);

物体

一个物体由几何体和材质(可以设置金属度,粗糙度等等一系列)构成

//设置几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
//基本材质不受光影响 常用
const material = new THREE.MeshBasicMaterial();  
//受光影响 常用
const material = new THREE.MeshStandardMaterial();
//融合构造物体
const cube = new THREE.Mesh(sphereGeometry, material);

运动动画

// 导入动画库
import gsap from "gsap";

var animate1 = gsap.to(cube.position, {
  x: 5,
  duration: 5,
  ease: "power1.inOut",
  //   设置重复的次数,无限次循环-1
  repeat: -1,
  //   往返运动
  yoyo: true,
  //   delay,延迟2秒运动
  delay: 2,
  onComplete: () => {
    console.log("动画完成");
  },
  onStart: () => {
    console.log("动画开始");
  },
});


gsap.to(cube.rotation, { x: 2 * Math.PI, duration: 5, ease: "power1.inOut" });

双击全屏,双击退出

window.addEventListener("dblclick", () => {
  const fullScreenElement = document.fullscreenElement;
  if (!fullScreenElement) {
    //   双击控制屏幕进入全屏,退出全屏
    // 让画布对象全屏
    renderer.domElement.requestFullscreen();
  } else {
    //   退出全屏,使用document对象
    document.exitFullscreen();
  }
  //   console.log(fullScreenElement);
});

添加gui(ui调节器)

import { gui } from "dat.gui";

const gui = new dat.GUI();

gui.add(pointLight.position, "x").min(-5).max(5).step(0.1);
gui.add(pointLight, "distance").min(0).max(5).step(0.001);
gui.add(pointLight, "decay").min(0).max(5).step(0.01);

贴图的使用

//导入置换贴图
const doorHeightTexture = textureLoader.load("./textures/door/height.jpg");
// 导入粗糙度贴图
const roughnessTexture = textureLoader.load("./textures/door/roughness.jpg");
// 导入金属贴图
const metalnessTexture = textureLoader.load("./textures/door/metalness.jpg");
// 导入法线贴图
const normalTexture = textureLoader.load("./textures/door/normal.jpg");


// 材质
const material = new THREE.MeshStandardMaterial({
  color: "#ffff00",
  map: doorColorTexture,
  alphaMap: doorAplhaTexture,
  transparent: true,
  aoMap: doorAoTexture,
  aoMapIntensity: 1,
  displacementMap: doorHeightTexture,
  displacementScale: 0.1,
  roughness: 1,
  roughnessMap: roughnessTexture,
  metalness: 1,
  metalnessMap: metalnessTexture,
  normalMap: normalTexture,
  //   opacity: 0.3,
  //   side: THREE.DoubleSide,
});

纹理加载的进度

// 单张纹理图的加载
event.onLoad = function () {
  console.log("图片加载完成");
};
event.onProgress = function (url, num, total) {
  console.log("图片加载完成:", url);
  console.log("图片加载进度:", num);
  console.log("图片总数:", total);
  let value = ((num / total) * 100).toFixed(2) + "%";
  console.log("加载进度的百分比:", value);
  div.innerHTML = value;
};
event.onError = function (e) {
  console.log("图片加载出现错误");
  console.log(e);
};

// 设置加载管理器
const loadingManager = new THREE.LoadingManager(
  event.onLoad,
  event.onProgress,
  event.onError
);
// 导入纹理
const textureLoader = new THREE.TextureLoader(loadingManager);
const doorColorTexture = textureLoader.load(
  "./textures/door/color.jpg"
  //   event.onLoad,
  //   event.onProgress,
  //   event.onError
);

加载 hdr 环境纹理

要有 import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";

import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
// 目标:设置环境纹理
// 加载hdr环境图
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("textures/hdr/002.hdr").then((texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping;
  scene.background = texture;
  scene.environment = texture;
});

或者用六张图片构成环境

// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMapTexture = cubeTextureLoader.load([
  "textures/environmentMaps/1/px.jpg",
  "textures/environmentMaps/1/nx.jpg",
  "textures/environmentMaps/1/py.jpg",
  "textures/environmentMaps/1/ny.jpg",
  "textures/environmentMaps/1/pz.jpg",
  "textures/environmentMaps/1/nz.jpg",
]);

const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20);
const material = new THREE.MeshStandardMaterial({
  metalness: 0.7,
  roughness: 0.1,
  envMap: envMapTexture,
});

光和阴影

光有各种光,当物体必须是MeshStandardMaterial 标准材质才会影响。

// 灯光阴影
// 1、材质要满足能够对光照有反应
// 2、设置渲染器开启阴影的计算 renderer.shadowMap.enabled = true;
// 3、设置光照投射阴影 directionalLight.castShadow = true;
// 4、设置物体投射阴影 sphere.castShadow = true;
// 5、设置物体接收阴影 plane.receiveShadow = true;
// 投射阴影
sphere.castShadow = true;
scene.add(sphere);

// // 创建平面
const planeGeometry = new THREE.PlaneBufferGeometry(10, 10);
const plane = new THREE.Mesh(planeGeometry, material);
plane.position.set(0, -1, 0);
plane.rotation.x = -Math.PI / 2;
// 接收阴影
plane.receiveShadow = true;
scene.add(plane);

// 灯光
// 环境光
const light = new THREE.AmbientLight(0xffffff, 0.5); // soft white light
scene.add(light);
//直线光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(10, 10, 10);
directionalLight.castShadow = true;
scene.add(directionalLight);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;

其中光有各种类型并且有各种属性可以设置

初步概念理解

顶点:把物体划分点,更好的控制物体,越多点越精细

法向:控制光照反射的位置

纹理:贴在物体上改变物体看起来的样子,各种图片贴上去

透明:利用贴图处理

粗糙:利用贴图处理

金属度:利用贴图处理

光照:利用贴图处理

贴图网站 (3dtextures.me)

看房的制作

两种方法:1、正方形六面加上六张图 cube.geometry.scale(1, 1, -1); 2、一个圆然后直接rgb sphere.geometry.scale(1, 1, -1);

关键点,图片在表面然后翻转

<template>
  <div class="container" ref="container"></div>
</template>

<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { ref, onMounted } from "vue";
// 初始化场景
const scene = new THREE.Scene();
// 初始化相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
// 设置相机位置
camera.position.z = 0.1;
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

const container = ref(null);

const render = () => {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
};

// 添加立方体
// const geometry = new THREE.BoxGeometry(10, 10, 10);
// // const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// // const cube = new THREE.Mesh(geometry, material);
// // scene.add(cube);

// // 4_b,
// var arr = ["4_l", "4_r", "4_u", "4_d", "4_b", "4_f"];
// var boxMaterials = [];

// arr.forEach((item) => {
//   // 纹理加载
//   let texture = new THREE.TextureLoader().load(`./imgs/living/${item}.jpg`);
//   // 创建材质
//   if (item === "4_u" || item === "4_d") {
//     texture.rotation = Math.PI;
//     texture.center = new THREE.Vector2(0.5, 0.5);
//     boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));
//   } else {
//     boxMaterials.push(new THREE.MeshBasicMaterial({ map: texture }));
//   }
// });
// const cube = new THREE.Mesh(geometry, boxMaterials);
// cube.geometry.scale(1, 1, -1);
// scene.add(cube);

// 添加球
const geometry = new THREE.SphereGeometry(5, 32, 32);
const loader = new RGBELoader();
loader.load("./imgs/hdr/Living.hdr", (texture) => {
  const material = new THREE.MeshBasicMaterial({ map: texture });
  const sphere = new THREE.Mesh(geometry, material);
  sphere.geometry.scale(1, 1, -1);
  scene.add(sphere);
});

// 挂载完毕之后获取dom
onMounted(() => {
  // 添加控制器
  const controls = new OrbitControls(camera, container.value);
  controls.enableDamping = true;
  container.value.appendChild(renderer.domElement);
  render();
});
</script>

<style>
</style>