Three.js 随机城市白膜教程

随机城市白膜 ·White Model· ▶ 在线运行案例

  • 案例合集:三维可视化功能案例(threehub.cn)
  • 开源仓库github地址:https://github.com/z2586300277/three-cesium-examples
  • 400个案例代码:网盘链接

你将学到什么

  • OrbitControls 相机轨道交互
  • 监听窗口resize同步更新 camera 与 renderer

效果说明

本案例演示随机城市白膜效果:生成仿真城市白膜;核心用到 OrbitControls。建议先打开文首在线案例查看动态画面,再对照下方源码逐步理解。

核心概念

  • Scene / Camera / WebGLRenderer构成最小渲染闭环;大场景可开logarithmicDepthBuffer缓解 Z-fighting。
  • OrbitControls提供轨道旋转/缩放;开启enableDamping后需在 animate 中controls.update()
  • 阅读下方完整源码时,建议从init/load/animate三条主线入手,再深入 shader 与工具函数。

实现步骤

  • 搭建灯光与环境(如有)
  • requestAnimationFrame 循环 update + render
  • 代码要点

    import * as THREE from 'three';

    import { OrbitControls } from "three/examples/jsm/Addons.js"; const DOM = document.getElementById('box')

    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight); camera.position.set(-1, 0.5, 1).setLength(75);

    camera.lookAt(scene.position);

    var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(innerWidth, innerHeight); renderer.setAnimationLoop(animationLoop); function animationLoop() { renderer.render(scene, camera); } DOM.appendChild(renderer.domElement);

    window.addEventListener("resize", () => { camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); renderer.setSize(innerWidth, innerHeight); });

    var controls = new OrbitControls(camera, renderer.domElement); controls.target.set(0, 12, 0);

    controls.update(); controls.enableDamping = true; controls.autoRotate = true;

    var light = new THREE.DirectionalLight('white', 3); light.position.set(1, 1, 1); scene.add(light); import { Mesh, MathUtils, PlaneGeometry, Color,BoxGeometry,MeshBasicMaterial } from 'three';

    /**

    • 生成仿真城市白膜
    */ const buildingGeometry = new BoxGeometry(1, 1, 1); buildingGeometry.translate(0, 0.5, 0); // 调整几何中心点 const buildingMaterial = new MeshBasicMaterial({ color: 0xcccccc }); function generateCityModel() { const citySize = 50; // 城市范围 const spacing = 10; // 建筑间隔 const maxDistance = citySize * spacing; // 最大影响范围 const plane = new PlaneGeometry(maxDistance2, maxDistance2); plane.rotateX(-Math.PI / 2) scene.add(new Mesh(plane)) for (let z = -citySize; z < citySize; z++) { for (let x = -citySize; x < citySize; x++) { // 跳过城市中心一定区域,避免过密 if (Math.abs(x) < 5 && Math.abs(z) < 5) continue;

    // 计算建筑位置 const positionX = x * spacing; const positionZ = z * spacing; const distanceFromCenter = Math.sqrt(positionX2 + positionZ2);

    // 根据距离中心的远近调整建筑高度和生成概率 const distanceFactor = 1 - MathUtils.clamp(distanceFromCenter / maxDistance, 0, 1); const heightScale = Math.pow(distanceFactor, 4); // 高度衰减曲线

    if (Math.random() < distanceFactor) { // 随机生成的概率 const building = new Mesh(buildingGeometry, buildingMaterial);

    // 设置建筑位置 let offset = (Math.random()0.5 - 1)spacing building.position.set(positionX + offset, 0, positionZ + offset);

    // 设置建筑缩放 building.scale.set( MathUtils.randInt(1, 4), // 宽度随机 1 + Math.floor(Math.random()heightScale35), // 高度与距离中心相关 MathUtils.randInt(1, 4) // 深度随机 ); // 随机红色 if (Math.random() < 0.1) { building.material = building.material.clone(); building.material.color = new Color('red'); } scene.add(building); } } } }

    generateCityModel()

    完整源码:GitHub

    小结

    • 本文提供随机城市白膜完整 Three.js 源码与在线 Demo,建议先运行案例再改 uniform/参数做二次实验
    • 更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库