Three.js 灯罩教程

Three.js 灯罩教程
灯罩 ·Lampshade· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么ShaderMaterial 自定义着色器实现核心视觉效果OrbitControls 相机轨道交互requestAnimationFrame渲染循环与resize自适应效果说明本案例演示灯罩效果基于 WebGL 实现「灯罩」可视化效果附完整可运行源码核心用到 ShaderMaterial、OrbitControls。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Scene / Camera / WebGLRenderer构成最小渲染闭环大场景可开logarithmicDepthBuffer缓解 Z-fighting。ShaderMaterial通过uniforms 自定义 GLSL 控制逐像素/逐点效果透明粒子常配合depthTest: false。OrbitControls提供轨道旋转/缩放开启enableDamping后需在 animate 中controls.update()。实现步骤创建 OrbitControls 并处理 resize定义 uniforms在 rAF 中更新并 render搭建灯光与环境如有requestAnimationFrame 循环 update render代码要点import {Color, CylinderGeometry, Group, Mesh, MeshBasicMaterial, MeshStandardMaterial, PerspectiveCamera, PlaneGeometry, PointLight, Scene, ShaderMaterial, SphereGeometry, WebGLRenderer } from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst size { width: window.innerWidth, height: window.innerHeight } const scene new Scene() scene.background new Color(#070630)const camera new PerspectiveCamera(45, size.width / size.height, 0.1, 1000) camera.position.set(30, 30, 30)const renderer new WebGLRenderer({ antialias: true }) renderer.setSize(size.width, size.height) renderer.setPixelRatio(window.devicePixelRatio) document.body.appendChild(renderer.domElement)const controls new OrbitControls(camera, renderer.domElement)class DeskLamp extends Group { constructor() { super() this.#createWick() this.#createLampshade() }/*灯芯/ #createWick() { const geometry new SphereGeometry(1, 32, 16, 0, Math.PI * 2, 0, Math.PI / 2) const material new MeshBasicMaterial({ color: 0xffffff }) const sphere new Mesh(geometry, material) sphere.position.set(0, 3, 0) this.#createLight(sphere) this.add(sphere) }/*灯罩/ #createLampshade() { const cylinderGeometry new CylinderGeometry(1, 5, 3, 32) const cylinderMaterial new ShaderMaterial({ transparent: true, uniforms: { color: { value: new Color(#CB00E3) } }, vertexShader:varying vec2 vUv; void main() { vUv uv; gl_Position projectionMatrixmodelViewMatrixvec4(position, 1.0); }, fragmentShader:uniform vec3 color; varying vec2 vUv; void main() { gl_FragColor vec4(color, vUv.y); }}) const cylinder new Mesh(cylinderGeometry, cylinderMaterial) cylinder.position.set(0, 1.7, 0) this.add(cylinder) }/*点光源/ #createLight(mesh) { const pointLight new PointLight(0xffffff, 1, 100) pointLight.power 1000 mesh.add(pointLight) } }const light1 new DeskLamp() light1.position.set(0, 10, 0) scene.add(light1)const light2 new DeskLamp() light2.position.set(10, 10, 0) scene.add(light2)const light3 new DeskLamp() light3.position.set(0, 10, 10) scene.add(light3)/**创建地面/ const planeGeometry new PlaneGeometry(100, 100) const planeMaterial new MeshStandardMaterial({ color: 0x999999, side: 2 }) const plane new Mesh(planeGeometry, planeMaterial) plane.rotation.x -Math.PI / 2 scene.add(plane)animate() function animate() {renderer.render(scene, camera) requestAnimationFrame(animate) }完整源码GitHub小结本文提供灯罩完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库