静态场景
<canvas id="mainCanvas"></canvas>
<script type="importmap">{"imports": {"three": "./js/build/three.module.js","three/addons/": "./js/jsm/"}}
</script>
<script type="module">import * as THREE from "three";import { TrackballControls } from "three/addons/controls/TrackballControls.js";import { GUI } from "three/addons/libs/lil-gui.module.min.js";function init() {const gui = new GUI();const renderer = new THREE.WebGLRenderer({canvas: document.getElementById("mainCanvas"),antialias: true,});renderer.setClearColor(new THREE.Color(0x000000));renderer.setSize(window.innerWidth, window.innerHeight);renderer.setPixelRatio(window.devicePixelRatio);renderer.shadowMap.enabled = true;const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(-30, 30, 30);camera.lookAt(scene.position);const spotLight = new THREE.SpotLight(0xffffff, 20, 0, Math.PI / 3, 0, 0.5);spotLight.position.set(-30, 30, -30);spotLight.castShadow = true;// spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024);// spotLight.shadow.camera.far = 130;// spotLight.shadow.camera.near = 40;scene.add(spotLight);gui.add(spotLight.position, "x", -50, 100).name("SpotLight光源位置x");gui.add(spotLight.position, "y", 0, 100).name("SpotLight光源位置y");gui.add(spotLight.position, "z", -50, 100).name("SpotLight光源位置z");gui.add(spotLight, "intensity", 0, 100).name("SpotLight光源强度");gui.add(spotLight, "angle", 0, 2 * Math.PI).name("SpotLight光源照射范围的角度");gui.add(spotLight, "distance", 0, 5000).name("SpotLight光源照射的最大距离");gui.add(spotLight, "decay", 0, 10).name("SpotLight光源沿着光照距离的衰退量");const ambienLight = new THREE.AmbientLight(0xffffff, 1);scene.add(ambienLight);gui.add(ambienLight, "intensity", 0, 100).name("AmbientLight光源强度");createTree(scene);createHouse(scene);createGroundPlane(scene);createBoundingWall(scene);const cubeGeometry = new THREE.BoxGeometry(4, 4, 4);const cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000,});const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);cube.castShadow = true;cube.position.set(-4, 2, 0);scene.add(cube);const sphereGeometry = new THREE.SphereGeometry(4, 20, 20);const sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff,});const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);sphere.position.set(20, 4, 2);sphere.castShadow = true;scene.add(sphere);const planeGeometry = new THREE.PlaneGeometry(60, 20);const planeMaterial = new THREE.MeshLambertMaterial({color: 0xaaaaaa,});const plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotation.x = -0.5 * Math.PI;plane.position.set(15, 0, 0);plane.receiveShadow = true;scene.add(plane);render();function render() {requestAnimationFrame(render);renderer.render(scene, camera);}}function createBoundingWall(scene) {const wallLeft = new THREE.BoxGeometry(70, 2, 2);const wallRight = new THREE.BoxGeometry(70, 2, 2);const wallTop = new THREE.BoxGeometry(2, 2, 50);const wallBottom = new THREE.BoxGeometry(2, 2, 50);const wallMaterial = new THREE.MeshLambertMaterial({color: 0xa0522d,});const wallLeftMesh = new THREE.Mesh(wallLeft, wallMaterial);const wallRightMesh = new THREE.Mesh(wallRight, wallMaterial);const wallTopMesh = new THREE.Mesh(wallTop, wallMaterial);const wallBottomMesh = new THREE.Mesh(wallBottom, wallMaterial);wallLeftMesh.position.set(15, 1, -25);wallRightMesh.position.set(15, 1, 25);wallTopMesh.position.set(-19, 1, 0);wallBottomMesh.position.set(49, 1, 0);scene.add(wallLeftMesh);scene.add(wallRightMesh);scene.add(wallBottomMesh);scene.add(wallTopMesh);}function createGroundPlane(scene) {const planeGeometry = new THREE.PlaneGeometry(70, 50);const planeMaterial = new THREE.MeshLambertMaterial({color: 0x9acd32,});const plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.receiveShadow = true;plane.rotation.x = -0.5 * Math.PI;plane.position.set(15, 0, 0);scene.add(plane);}function createHouse(scene) {const roof = new THREE.ConeGeometry(5, 4);const base = new THREE.CylinderGeometry(5, 5, 6);const roofMesh = new THREE.Mesh(roof,new THREE.MeshLambertMaterial({color: 0x8b7213,}));const baseMesh = new THREE.Mesh(base,new THREE.MeshLambertMaterial({color: 0xffe4c4,}));roofMesh.position.set(25, 8, 0);baseMesh.position.set(25, 3, 0);roofMesh.receiveShadow = true;baseMesh.receiveShadow = true;roofMesh.castShadow = true;baseMesh.castShadow = true;scene.add(roofMesh);scene.add(baseMesh);}function createTree(scene) {const trunk = new THREE.BoxGeometry(1, 8, 1);const leaves = new THREE.SphereGeometry(4);const trunkMesh = new THREE.Mesh(trunk,new THREE.MeshLambertMaterial({color: 0x8b4513,}));const leavesMesh = new THREE.Mesh(leaves,new THREE.MeshLambertMaterial({color: 0x00ff00,}));trunkMesh.position.set(-10, 4, 0);leavesMesh.position.set(-10, 12, 0);trunkMesh.castShadow = true;trunkMesh.receiveShadow = true;leavesMesh.castShadow = true;leavesMesh.receiveShadow = true;scene.add(trunkMesh);scene.add(leavesMesh);}init();
</script>
管道动画
<canvas id="mainCanvas"></canvas>
<script type="importmap">{"imports": {"three": "./js/build/three.module.js","three/addons/": "./js/jsm/"}}
</script>
<script type="module">import * as THREE from "three";const renderer = new THREE.WebGLRenderer({canvas: document.getElementById("mainCanvas"),antialias: true,});renderer.setClearColor(new THREE.Color(0x000000));renderer.setSize(window.innerWidth, window.innerHeight);renderer.setPixelRatio(window.devicePixelRatio);renderer.shadowMap.enabled = true;const scene = new THREE.Scene();const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(-30, 30, 30);camera.lookAt(scene.position);const spotLight = new THREE.SpotLight(0xffffff, 20, 0, Math.PI / 3, 0, 0.5);spotLight.position.set(-30, 30, -30);spotLight.castShadow = true;scene.add(spotLight);const ambienLight = new THREE.AmbientLight(0xffffff, 1);scene.add(ambienLight);const path = new THREE.CatmullRomCurve3([new THREE.Vector3(-5, 2, 9),new THREE.Vector3(-1, 4, 4),new THREE.Vector3(0, 0, 0),new THREE.Vector3(6, -6, 0),new THREE.Vector3(9, -4, 6),new THREE.Vector3(12, 3, 3),]);// 三维样条曲线作为TubeGeometry参数生成管道const geometry = new THREE.TubeGeometry(path, 100, 5, 30);const texLoader = new THREE.TextureLoader();//纹理贴图texLoader.load("../images/square.jpg", (texture) => {//UV坐标U方向阵列模式texture.wrapS = THREE.RepeatWrapping;// 纹理沿着管道方向阵列(UV坐标U方向)texture.repeat.x = 100;const material = new THREE.MeshBasicMaterial({map: texture,side: THREE.DoubleSide,});const mesh = new THREE.Mesh(geometry, material);scene.add(mesh);});let i = 0;render();function render() {const pointsArr = path.getSpacedPoints(500);if (i < pointsArr.length - 1) {camera.position.copy(pointsArr[i]);camera.lookAt(pointsArr[i + 1]);i += 1;} else {i = 0;}renderer.render(scene, camera);requestAnimationFrame(render);}
</script>