ThreeJS-炫酷球形机器人(三十一)
素材:
链接: https://pan.baidu.com/s/1S8V2gUFwiCjLYIcN9GFu-A
提取码: rjpx
关键代码:
//添加底部旋转纹理
const videoElem = document.createElement('video');
videoElem.src = 'three/robot-footer.mp4';
videoElem.loop = true;
videoElem.muted = true;
videoElem.play();
const videoLoader = new THREE.VideoTexture(videoElem);
const planeGeometry = new THREE.PlaneBufferGeometry(16, 9);
const meshMaterial = new THREE.MeshBasicMaterial({
transparent: true,
alphaMap: videoLoader,
map: videoLoader,
side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(planeGeometry, meshMaterial);
mesh.rotation.x = -Math.PI/2;
mesh.position.set(0, 0.2, 0);
scene.add(mesh);
//创建镜面
const reflectorPlaneGeometry = new THREE.PlaneBufferGeometry(100, 100);
const reflector = new Reflector(reflectorPlaneGeometry, {
textureWidth: window.innerWidth,
textureHeight: window.innerHeight,
color: 0xffffff,
});
reflector.rotation.x = -Math.PI/2;
scene.add(reflector);
完整代码:
<template>
<div id="three_div"></div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { Reflector } from "three/examples/jsm/objects/Reflector";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import gsap from "gsap";
export default {
name: "HOME",
components: {
// vueQr,
// glHome,
},
data() {
return {};
},
mounted() {
//使用控制器控制3D拖动旋转OrbitControls
//控制3D物体移动
//1.创建场景
const scene = new THREE.Scene();
//2.创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
20000
);
//设置相机位置
camera.position.set(0, 0, 10);
//将相机添加到场景
scene.add(camera);
const axesHelper = new THREE.AxesHelper(5,5,5);
scene.add(axesHelper);
//创建背景星空
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync('three/robot_background.hdr').then( loader => {
loader.mapping = THREE.EquirectangularReflectionMapping;
scene.background = loader;
});
//添加机器人模型
const gltf = new GLTFLoader().setPath('three/glb/');
//创建解码加载器
const dracoLoader = new DRACOLoader().setDecoderPath('three/draco/gltf/');
//设置解码器
gltf.setDRACOLoader(dracoLoader);
//加载模型
gltf.load('robot.glb', gltf => {
scene.add(gltf.scene);
})
//添加灯光
const light1 = new THREE.DirectionalLight(0xffffff, 1);
light1.position.set(10, 10, 5);
scene.add(light1);
const light2 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(10, 10, -5);
scene.add(light2);
const light3 = new THREE.DirectionalLight(0xffffff, 1);
light3.position.set(-10, 10, 5);
scene.add(light3);
//添加底部旋转纹理
const videoElem = document.createElement('video');
videoElem.src = 'three/robot-footer.mp4';
videoElem.loop = true;
videoElem.muted = true;
videoElem.play();
const videoLoader = new THREE.VideoTexture(videoElem);
const planeGeometry = new THREE.PlaneBufferGeometry(16, 9);
const meshMaterial = new THREE.MeshBasicMaterial({
transparent: true,
alphaMap: videoLoader,
map: videoLoader,
side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(planeGeometry, meshMaterial);
mesh.rotation.x = -Math.PI/2;
mesh.position.set(0, 0.2, 0);
scene.add(mesh);
//创建镜面
const reflectorPlaneGeometry = new THREE.PlaneBufferGeometry(100, 100);
const reflector = new Reflector(reflectorPlaneGeometry, {
textureWidth: window.innerWidth,
textureHeight: window.innerHeight,
color: 0xffffff,
});
reflector.rotation.x = -Math.PI/2;
scene.add(reflector);
//初始化渲染器
const render = new THREE.WebGLRenderer({
//设置抗锯齿,防失真
antialis: true,
//对数深度缓冲区,防止模型闪烁
logarithmicdepthbuffer: true,
});
/*设置场景渲染编码threejs将贴图的编码都默认设置为THREE.LinearEncoding,
*导致图片色彩失真(色彩不像正常那么鲜艳,会灰蒙蒙的),所以务必将场景中的所有贴图的编码都调整为THREE.sRGBEncoding
*/
render.outputEncoding = THREE.sRGBEncoding;
//设置渲染器的尺寸
render.setSize(window.innerWidth, window.innerHeight);
//清除默认设置颜色
render.setClearColor("#000");
//设置曝光类型(电影类型、文本类型、游戏类型),电影类型
render.toneMapping = THREE.ACESFilmicToneMapping;
//曝光强度
render.toneMappingExposure = 0.5;
//开启物理灯光,使灯光效果更佳真实Correct(准确)
render.physicallyCorrectLights = true;
//创建轨道控制器,可以拖动,控制的是摄像头
const controls = new OrbitControls(camera, render.domElement);
//设置控制阻尼,让控制器有更真实的效果
controls.enableDamping = true;
//将webgl渲染的canvas内容添加到body上
document.getElementById("three_div").appendChild(render.domElement);
//渲染下一帧的时候就会调用回调函数
let renderFun = () => {
//更新阻尼数据
controls.update();
//需要重新绘制canvas画布
render.render(scene, camera);
//监听屏幕刷新(60HZ,120HZ),每次刷新触发一次requestAnimationFrame回调函数
//但是requestAnimationFrame的回调函数注册生命只有一次,因此需要循环注册,才能达到一直调用的效果
window.requestAnimationFrame(renderFun);
};
// window.requestAnimationFrame(renderFun);
renderFun();
//画布全屏
window.addEventListener("dblclick", () => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
//document.documentElement.requestFullscreen();
render.domElement.requestFullscreen();
}
});
//监听画面变化,更新渲染画面,(自适应的大小)
window.addEventListener("resize", () => {
//更新摄像机的宽高比
camera.aspect = window.innerWidth / window.innerHeight;
//更新摄像机的投影矩阵
camera.updateProjectionMatrix();
//更新渲染器宽度和高度
render.setSize(window.innerWidth, window.innerHeight);
//设置渲染器的像素比
render.setPixelRatio(window.devicePixelRatio);
});
},
methods: {},
};
</script>
<style scoped lang="scss">
* {
margin: 0;
padding: 0;
}
.home-content {
position: fixed;
top: 0;
right: 20px;
}
.select-item-color {
width: 50px;
height: 50px;
border: 1px solid #ccc;
margin: 10px;
display: inline-block;
cursor: pointer;
border-radius: 10px;
}
.select {
display: flex;
}
</style>
效果图: