如何在现有Three.js项目中集成THREE.Terrain实现程序化地形生成
THREE.js 集成THREE.Terrain程序化地形实现方案
实现步骤
- 第一步:引入THREE.Terrain依赖
可以选择两种引入方式:- npm安装:执行
npm install three.terrain后,在代码中引入import * as THREE.Terrain from 'three.terrain' - 静态资源引入:将库文件下载到本地后,通过
<script>标签在Three.js之后引入
- npm安装:执行
- 第二步:添加地形生成逻辑
在现有代码的光照初始化完成后、animate函数前添加地形生成代码,核心逻辑为:先定义地形基础参数,通过THREE.Terrain的高度生成方法生成噪声高度数据,将数据赋值给平面几何体的顶点,计算法线后生成网格加入场景。 - 第三步:效果调整
可以修改地形分段数、高度缩放系数、噪声频率等参数,调整地形的起伏效果、精细度和陡峭程度。
完整修改后的代码
const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,0.01, 100000); camera.position.set(200, 80, 200); // 调整相机位置方便查看完整地形 const renderer = new THREE.WebGLRenderer(); renderer.shadowMap.enabled = true; renderer.setClearColor(0xcccccc, 1.0); renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); const controls = new THREE.OrbitControls( camera,renderer.domElement ); controls.screenSpacePanning = true; const sceneMeshes = []; const axesHelper = new THREE.AxesHelper( 1000 ); scene.add( axesHelper ); axesHelper.position.y = 0 const shadowLight = new THREE.DirectionalLight(0xffffff, 0.6); shadowLight.position.set(150, 350, 350); shadowLight.castShadow = true shadowLight.shadow.camera.left = -400; shadowLight.shadow.camera.right = 400; shadowLight.shadow.camera.top = 400; shadowLight.shadow.camera.bottom = -400; shadowLight.shadow.camera.near = 1; shadowLight.shadow.camera.far = 10000; shadowLight.shadow.mapSize.width = 2048; shadowLight.shadow.mapSize.height = 2048; scene.add(shadowLight); // ---------- 新增地形生成代码开始 ---------- // 地形基础参数定义 const terrainWidth = 400; // 地形宽度 const terrainDepth = 400; // 地形深度 const segments = 128; // 地形分段数,数值越高地形越精细,性能消耗也越高 const heightScale = 30; // 地形高度缩放系数,数值越高地形起伏越陡峭 // 生成高度数据 const heightData = THREE.Terrain.PerlinDiamond( segments + 1, // x轴顶点数 segments + 1, // z轴顶点数 { frequency: 2.5, // 噪声频率,数值越低地形越平缓 amplitude: heightScale } ); // 创建地形几何体 const terrainGeo = new THREE.PlaneGeometry(terrainWidth, terrainDepth, segments, segments); // 替换顶点y轴数值为生成的高度数据 const vertices = terrainGeo.attributes.position.array; for (let i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) { vertices[j + 1] = heightData[i]; } // 重新计算法线保证光照效果正确 terrainGeo.computeVertexNormals(); // 地形材质,可以根据需求替换为纹理材质、自定义Shader材质等 const terrainMat = new THREE.MeshStandardMaterial({ color: 0x3a5f0b, // 草绿色,可自定义 side: THREE.DoubleSide }); // 生成地形网格 const terrain = new THREE.Mesh(terrainGeo, terrainMat); terrain.rotation.x = -Math.PI / 2; // 平面默认是xy平面,旋转后变为xz平面作为地面 terrain.receiveShadow = true; // 允许接收阴影 scene.add(terrain); sceneMeshes.push(terrain); // ---------- 新增地形生成代码结束 ---------- const animate = function (){ requestAnimationFrame( animate ); controls.update(); // 新增controls更新,保证轨道控制生效 renderer.render( scene, camera ); }; animate();
可调参数说明
- 修改
segments可以调整地形的精细程度,建议根据性能需求设置为32/64/128/256 - 修改
heightScale可以调整地形的最大高度,数值越大起伏越明显 - 修改噪声参数
frequency可以调整地形的起伏密度,数值越小地形越平缓,越大越破碎 - 材质可以替换为多层纹理混合、顶点色着色等方案,实现雪地、草地、砂石等不同地表效果
内容的提问来源于stack exchange,提问作者It's Joker
相关产品推荐
相关产品推荐

