参考资料
知识点
- 透视投影相机PerspectiveCamera
- WebGL渲染器WebGLRenderer
- 辅助观察坐标系AxesHelper
- 漫反射网格材质MeshLambertMaterial
- 点光源PointLight
- 点光源辅助观察PointLightHelper
- 环境光AmbientLight
- 平行光DirectionalLight
- 平行光辅助观察DirectionalLightHelper
- 相机控件OrbitControls
- 请求动画帧window.requestAnimationFrame
- canvas画布宽高度动态变化
- 性能监控Stats
代码实现
-
相机、渲染器、光
javascript<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> </head> <body> </body> <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 --> <script type="importmap"> { "imports": { "three": "./js/three.module.js", "three/addons/": "../three.js/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; const width = 800 const height = 500 // 场景 const scene = new THREE.Scene(); // 几何体 const geometry = new THREE.BoxGeometry(100, 100, 100); // 材质 // MeshBasicMaterial:不受光 // MeshLambertMaterial:受光 const material = new THREE.MeshLambertMaterial({ color:0x0000ff, }); // 网格模型:物体 const mesh = new THREE.Mesh(geometry, material); mesh.position.set(0, 0, 0); scene.add(mesh); // 坐标系 const axes = new THREE.AxesHelper(200); scene.add(axes); // // 点光源 // const pointLight = new THREE.PointLight( 0xffffff, 1.0, 0, 0); // pointLight.position.set(-200, 200, 200 ); // scene.add( pointLight ); // // 辅助点光源 // const pointLightHelper = new THREE.PointLightHelper( pointLight, 10 ); // scene.add( pointLightHelper ); // 环境光 const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2); scene.add( ambientLight ); // 平行光 const directionalLight = new THREE.DirectionalLight( 0xffffff, 1, 0, 0); // directionalLight.position.set(100, 0, 0); // directionalLight.position.set(0, 100, 0); // directionalLight.position.set(100, 100, 100); directionalLight.position.set(100, 60, 50); directionalLight.target = mesh; scene.add( directionalLight ); // 辅助平行光 const directionalLightHelper = new THREE.DirectionalLightHelper( directionalLight, 10 ); scene.add( directionalLightHelper ); // 相机 const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); camera.position.set(200, 200, 200); camera.lookAt(scene.position); // 渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height); renderer.render(scene, camera); document.body.appendChild(renderer.domElement); // 控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.addEventListener('change', () => { renderer.render(scene, camera); }); </script> </html>
-
动画
javascript<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> </head> <body> </body> <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 --> <script type="importmap"> { "imports": { "three": "./js/three.module.js", "three/addons/": "../three.js/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; const width = 800 const height = 500 // 场景 const scene = new THREE.Scene(); // 几何体 const geometry = new THREE.BoxGeometry(100, 100, 100); // 材质 const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.5 }); // 网格模型:物体 const mesh = new THREE.Mesh(geometry, material); mesh.position.set(0, 0, 0); scene.add(mesh); // 坐标系 const axes = new THREE.AxesHelper(200); scene.add(axes); // 相机 const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); camera.position.set(200, 200, 200); camera.lookAt(scene.position); // 渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height); renderer.render(scene, camera); document.body.appendChild(renderer.domElement); // 动画渲染 // 跟踪时间 var clock = new THREE.Clock(); function render() { const spt = clock.getDelta() * 1000; console.log('🚀 ~ file: animation.html:59 ~ render ~ spt:', spt) requestAnimationFrame(render); mesh.rotation.y += 0.01; renderer.render(scene, camera); } render(); // 控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.addEventListener('change', () => { // 因为动画渲染了,所以这里可以省略 // renderer.render(scene, camera); }); </script> </html>
-
画布动态变化
javascript<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> <style> body { margin: 0; overflow: hidden; } </style> </head> <body> </body> <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 --> <script type="importmap"> { "imports": { "three": "./js/three.module.js" } } </script> <script type="module"> import * as THREE from 'three'; let width = window.innerWidth; let height = window.innerHeight; // 场景 const scene = new THREE.Scene(); // 几何体 const geometry = new THREE.BoxGeometry(100, 100, 100); // 材质 const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.5 }); // 网格模型:物体 const mesh = new THREE.Mesh(geometry, material); mesh.position.set(0, 0, 0); scene.add(mesh); // 坐标系 const axes = new THREE.AxesHelper(200); scene.add(axes); // 相机 const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); camera.position.set(200, 200, 200); camera.lookAt(scene.position); // 渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height); renderer.render(scene, camera); document.body.appendChild(renderer.domElement); // 填满浏览器 window.onresize = function () { width = window.innerWidth; height = window.innerHeight; renderer.setSize(width, height); camera.aspect = width / height; camera.updateProjectionMatrix(); } </script> </html>
-
性能监控
javascript<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> </head> <body> </body> <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 --> <script type="importmap"> { "imports": { "three": "./js/three.module.js", "three/addons/": "../three.js/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import Stats from 'three/addons/libs/stats.module.js'; const width = 800 const height = 500 // 场景 const scene = new THREE.Scene(); // 几何体 const geometry = new THREE.BoxGeometry(100, 100, 100); // 材质 const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.5 }); // 网格模型:物体 const mesh = new THREE.Mesh(geometry, material); mesh.position.set(0, 0, 0); scene.add(mesh); for (let i = 0; i < 1000; i++) { // 几何体 const geometry = new THREE.BoxGeometry(5, 5, 5); // 材质 const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, transparent: true, opacity: 0.5 }); // 网格模型:物体 const mesh = new THREE.Mesh(geometry, material); mesh.position.set((Math.random() - 0.5) * 200, (Math.random() - 0.5) * 200, (Math.random() - 0.5) * 200); scene.add(mesh); } // 坐标系 const axes = new THREE.AxesHelper(200); scene.add(axes); // 相机 const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000); camera.position.set(200, 200, 200); camera.lookAt(scene.position); // 渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(width, height); renderer.render(scene, camera); document.body.appendChild(renderer.domElement); // 性能监控 const stats = new Stats() document.body.appendChild(stats.domElement); // 动画渲染 // 跟踪时间 var clock = new THREE.Clock(); function render() { stats.update() const spt = clock.getDelta() * 1000; requestAnimationFrame(render); mesh.rotation.y += 0.01; renderer.render(scene, camera); } render(); </script> </html>