【图中效果完整代码位于文章末】
在三维图形开发中,镜面反射是一种常见且引人注目的视觉效果,它能够极大地提升场景的真实感。本文将引导你通过Three.js框架实现一个简单的镜面反射效果。我们将创建两个具有镜面反射效果的立方体,并让它们反射不同的环境。
目录
准备工作
首先,确保你已经安装了Three.js库,并在你的项目中正确配置。此外,本教程还将用到环境贴图(Equirectangular或Cube Map格式),这些贴图用于模拟周围环境的反射。
如何创建360度全景贴图可前往上一篇文章👇
👉【threejs教程9】threejs加载360全景图(VR)的两种方法
1.场景初始化
一切从初始化场景、相机、渲染器开始。我们设置相机位置,并调整渲染器大小以适应浏览器窗口。
function init() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 假设你已加载了环境贴图textureCube和textureEquirec
// 加载过程此处省略,确保你有正确的贴图路径
}
2.创建镜面反射材质
接下来,我们创建两种材质,分别使用立方体贴图(Cube Map)和等距柱投影贴图(Equirectangular Map)作为环境贴图,来实现不同的镜面反射效果。
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material1 = new THREE.MeshStandardMaterial({
metalness: 1, // 设置金属度,增强反射效果
roughness: 0, // 设置粗糙度为0,得到完全光滑的表面
envMap: textureCube, // 应用立方体贴图
envMapIntensity: 1, // 控制环境贴图的亮度
});
const material2 = new THREE.MeshStandardMaterial({
metalness: 1,
roughness: 0,
envMap: textureEquirec, // 应用等距柱投影贴图
envMapIntensity: 1,
});
3.添加立方体到场景
使用上面创建的材质,我们为两个立方体赋予镜面反射效果,并将它们添加到场景中。
const cube1 = new THREE.Mesh(geometry, material1);
const cube2 = new THREE.Mesh(geometry, material2);
scene.add(cube1, cube2);
cube1.position.set(5, 0, 0);
4.动画与渲染
最后,我们需要一个动画循环来不断更新和渲染场景。这里假设你已经设置了controls,比如OrbitControls,来允许用户旋转观察场景。
function animate() {
requestAnimationFrame(animate);
controls.update(); // 更新控制器状态
renderer.render(scene, camera); // 渲染每一帧
}
animate();
完整代码如下
<template></template>
<script setup>
import * as THREE from 'three'
import { onMounted } from 'vue'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const scene = new THREE.Scene()
// 加载背景
const textureLoader = new THREE.TextureLoader()
const textureEquirec = textureLoader.load('./img/bg1.jpg')
textureEquirec.mapping = THREE.EquirectangularReflectionMapping
textureEquirec.colorSpace = THREE.SRGBColorSpace
scene.background = textureEquirec
const loader = new THREE.CubeTextureLoader()
loader.setPath('./img/')
const textureCube = loader.load([
'posx.jpg',
'negx.jpg',
'posy.jpg',
'negy.jpg',
'posz.jpg',
'negz.jpg',
])
// scene.background = textureCube
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
const renderer = new THREE.WebGLRenderer({ antialias: true })
const controls = new OrbitControls(camera, renderer.domElement)
onMounted(() => {
init()
})
function init() {
camera.position.set(0, 0, 5)
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const geometry = new THREE.BoxGeometry(2, 2, 2)
const material1 = new THREE.MeshStandardMaterial({
metalness: 1, // 镜面反射程度
roughness: 0, // 平滑度,0为完全光滑
envMap: textureCube, // 使用环境贴图
envMapIntensity: 1, // 环境贴图的强度
})
const material2 = new THREE.MeshStandardMaterial({
metalness: 1, // 镜面反射程度
roughness: 0, // 平滑度,0为完全光滑
envMap: textureEquirec, // 使用环境贴图
envMapIntensity: 1, // 环境贴图的强度
})
const cube1 = new THREE.Mesh(geometry, material1)
const cube2 = new THREE.Mesh(geometry, material2)
scene.add(cube1, cube2)
cube1.position.set(5, 0, 0)
function animate() {
requestAnimationFrame(animate)
controls.update()
renderer.render(scene, camera)
}
animate()
}
</script>
总结
通过以上步骤,你已经在Three.js中成功创建了两个具有镜面反射效果的立方体。通过调整材质的metalness、roughness以及envMapIntensity等属性,可以进一步微调反射效果,以满足不同的视觉需求。此外,对于更复杂的动态反射需求,还可以探索Three.js提供的高级技术,如屏幕空间反射(SSR)等。