threejs+vue/02 360场景/反光球/镜子

245 阅读1分钟

一、import引入相关功能

import * as THREE from "three"; // 引入three.js
import { LinearMipMapLinearFilter, RGBFormat } from "three"; // 引入三维纹理类型 
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 引入控制器
import { Reflector } from "three/examples/jsm/objects/Reflector"; // 反光球/反射器/镜子

二、基础场景搭建

let scene, camera, renderer, container, light, controls; // 定义变量
scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(
60,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, 0, -200);
camera.lookAt(scene.position);

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);

container = this.$refs.three;
container.appendChild(renderer.domElement);

light = new THREE.AmbientLight();
scene.add(light);

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

三、第一种实现方案(天空盒)

六张不同视角的图片

neg-x.jpg neg-y.jpg neg-z.jpg pos-x.jpg pos-y.jpg pos-z.jpg
let geometry = new THREE.BoxGeometry(5, 5, 5);
geometry.scale(1, 1, -1);
let materials = []; // 贴图数组
for (let i = 0; i < 6; i++) {
  let texture = new THREE.TextureLoader().load(
    require(`../../assets/image/${i + 1}.jpg`)
  );
  materials.push(new THREE.MeshBasicMaterial({ map: texture }));
}
let mesh = new THREE.Mesh(geometry, materials);
mesh.position.set(0, 0, 0);
scene.add(mesh);
camera.position.set(0, 0, 0.01); // 相机位置
camera.lookAt(0, 0, 0);

效果如下

GIF 2022-7-25 13-58-25.gif

四、第二种实现方案(环境贴图)

let urls = [
require("../../assets/image/pos-x.jpg"),
require("../../assets/image/neg-x.jpg"),
require("../../assets/image/pos-y.jpg"),
require("../../assets/image/neg-y.jpg"),
require("../../assets/image/pos-z.jpg"),
require("../../assets/image/neg-z.jpg"),
];
let cubeLoader = new THREE.CubeTextureLoader();
let cubMap = cubeLoader.load(urls);
scene.background = cubMap;

效果如下

GIF 2022-7-25 15-47-27.gif

五、加入反光球

1.使用环境贴图

let sphereGeometry = new THREE.SphereGeometry(30, 60, 60);
let sphereMaterial = new THREE.MeshPhongMaterial({
    envMap: cubMap, // 使用环境贴图
});
let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(100, 0, 0);
scene.add(sphere);

效果图

image.png

使用环境贴图只会反射贴图,并不会与周围环境有交互效果,想要与周围环境有反射效果需要使用CubeCamera

2.使用CubeCamera

let cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256, {
    format: RGBFormat,
    generateMipmaps: true,
    minFilter: LinearMipMapLinearFilter,
});

let cubeCamera = new THREE.CubeCamera(1, 10000, cubeRenderTarget);
scene.add(cubeCamera);

// 加入一个新的球体 
let sphereGeometry1 = new THREE.SphereGeometry(30, 32, 32);
let sphereMaterial1 = new THREE.MeshBasicMaterial({
    color: "#f00",
});
let sphere1 = new THREE.Mesh(sphereGeometry1, sphereMaterial1);
sphere1.position.set(-100, 0, 0);


// 原来的反光球只需要更改envMap属性
let sphereGeometry = new THREE.SphereGeometry(30, 60, 60);
let sphereMaterial = new THREE.MeshPhongMaterial({
    envMap: cubeRenderTarget.texture, //使用CubeCamera
});
let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(100, 0, 0);
scene.add(sphere);

效果图

image.png

六、加入镜子

let glass = new THREE.PlaneGeometry(300, 300);
let glassPlane = new Reflector(glass, {
    clipBias: 0.003,
    textureWidth: window.innerWidth * window.devicePixelRatio,
    textureHeight: window.innerHeight * window.devicePixelRatio,
}); //第一面镜子
let glassPlaneCopy = new Reflector(glass, {
    clipBias: 0.003,
    textureWidth: window.innerWidth * window.devicePixelRatio,
    textureHeight: window.innerHeight * window.devicePixelRatio,
}); // 第二面镜子
glassPlane.position.set(1, 0, 0);
glassPlane.rotation.y = Math.PI / 2;

glassPlaneCopy.position.set(-1, 0, 0);
glassPlaneCopy.rotation.y = -Math.PI / 2;

scene.add(glassPlane, glassPlaneCopy);

最终效果

GIF 2022-7-25 16-12-10.gif