1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| <script setup> import { ref, onMounted, onBeforeUnmount } from 'vue'; import { useRouter } from 'vue-router' import * as THREE from 'three' import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import gsap from 'gsap'
const router = useRouter() const width = window.innerWidth, height = window.innerHeight; const threeContainer = ref(null); const guiContainer = ref(null); // 创建场景 const scene = new THREE.Scene(); // WebGL渲染器 const renderer = new THREE.WebGLRenderer(); // 创建相机 const camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 ); // 添加轨道控制器 const controls = new OrbitControls(camera, renderer.domElement) // 坐标辅助 const axesHelper = new THREE.AxesHelper( 5 ); const smallBall = new THREE.Mesh( new THREE.SphereGeometry( 0.1, 20, 20 ), new THREE.MeshBasicMaterial({ color: 0xff0000 }) ); // 创建时钟 const clock = new THREE.Clock(); // 创建GUI const gui = new GUI({ width: 400, // 设置gui的宽度 closeOnTop: true, // 设置gui是否在顶部关闭 autoPlace: true, // 设置gui是否自动放置在页面中 title: 'Controls', // 设置gui的标题 });
onMounted(() => { init() })
onBeforeUnmount(() => { gui.destroy(); // 销毁GUI实例 })
const init = () => { camera.position.set( 0, 0, 10 ); scene.add( camera ); // camera.lookAt( 0, 0, 0 ); // 默认原点 const sphereGeometry = new THREE.SphereGeometry(1, 64, 64); const material = new THREE.MeshStandardMaterial(); const sphere = new THREE.Mesh( sphereGeometry, material ); sphere.castShadow = true; // 设置物体投射阴影 scene.add( sphere ); // 创建平面 const palneGeometry = new THREE.PlaneGeometry(50, 50) const plane = new THREE.Mesh(palneGeometry, 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.75 ); scene.add(light);
smallBall.position.set( 2, 2, 2 ); // 点光源 const pointLight = new THREE.PointLight( 0xff0000, 0.75 ) // pointLight.position.set( 2, 2, 2 ); pointLight.castShadow = true; // 设置光照投射阴影 pointLight.target = smallBall pointLight.distance = 0; pointLight.decay = 0; smallBall.add( pointLight ); scene.add( smallBall ); gui.add( pointLight.position, 'x' ).min(-5).max(5).step(0.1); gui.add( pointLight, 'distance').min(0).max(1).step(0.01); gui.add( pointLight, 'decay' ).min(0).max(5).step(0.01); // 将坐标轴添加到场景中 scene.add( axesHelper ); renderer.shadowMap.enabled = true; // 开启场景中的阴影贴图 renderer.physicallyCorrectLights = true; // 开启物理正确的光照 renderer.shadowMap.resolution = 1024; // 设置阴影贴图的分辨率 renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 设置阴影贴图的类型 camera.aspect = width / height; // 更新相机宽高比 camera.updateProjectionMatrix(); // 更新相机投影矩阵 controls.enableDamping = true; // 启用阻尼(惯性) renderer.setAnimationLoop( animate ); animate(); // 将渲染器添加到DOM中 threeContainer.value.appendChild( renderer.domElement ); // 将GUI添加到页面中 guiContainer.value.appendChild( gui.domElement ); }
const animate = () => { const time = clock.getElapsedTime(); smallBall.position.x = Math.sin(time) * 2; smallBall.position.z = Math.cos(time) * 2; controls.update(); // 更新轨道控制器 renderer.setSize( width, height ); renderer.render( scene, camera ); // 将场景和相机渲染到屏幕上 // requestAnimationFrame(animate); }
const back = () => { router.go(-1) } </script>
<template> <div class="btn-group"> <button class="back-btn" @click="back">返回</button> </div> <div ref="threeContainer" class="threeContainer"></div> <div ref="guiContainer"></div> </template>
|