Three.js 魔幻山体教程

发布时间:2026/7/7 8:16:40

Three.js 魔幻山体教程 魔幻山体 ·Contour· ▶ 在线运行案例案例合集三维可视化功能案例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()。实现步骤搭建 Scene、PerspectiveCamera、WebGLRenderer挂载 canvas 并处理resize定义 uniforms / onBeforeCompile 或 ShaderMaterial编写 GLSL 与材质参数创建 OrbitControls及 Raycaster 等交互控件若源码包含在requestAnimationFrame循环中更新状态并 renderCesium 为viewer.render或自动渲染代码要点import * as THREE from three;import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js; // 魔幻山体-等高线示意 const box document.getElementById(box); const scene new THREE.Scene(); scene.background new THREE.Color(0.5, 1, 0.875); scene.fog new THREE.Fog(scene.background, 20, 45); const camera new THREE.PerspectiveCamera( 75, box.clientWidth / box.clientHeight, 0.1, 1000, ); camera.position.set(0, 10, 10); const renderer new THREE.WebGLRenderer(); renderer.setSize(box.clientWidth, box.clientHeight); box.appendChild(renderer.domElement); new OrbitControls(camera, renderer.domElement); window.onresize () { renderer.setSize(box.clientWidth, box.clientHeight); camera.aspect box.clientWidth / box.clientHeight; camera.updateProjectionMatrix(); };animate(); function animate() { // uniforms.iTime.value 0.01 requestAnimationFrame(animate); renderer.render(scene, camera); }// 添加一个plane import { Clock, DoubleSide, Mesh, PlaneGeometry, ShaderMaterial } from three const add_plane () { const clock new Clock(); const planeGeometry new PlaneGeometry(50, 50, 500, 500); planeGeometry.rotateX(-Math.PI / 2) let uniforms { u_time: { value: clock.getDelta() } } // shader material const vertexShader vec3 hash(vec3 p) { p vec3( dot(p, vec3(127.1, 311.7, 74.7)), dot(p, vec3(269.5, 183.3, 246.1)), dot(p, vec3(113.5, 271.9, 124.6))); return fract(sin(p) * 43758.5453123); } // returns 3D value noise float noise( in vec3 x ) { // grid vec3 p floor(x); vec3 w fract(x); // quintic interpolant vec3 u www(w(w*6.0-15.0)10.0); // gradients vec3 ga hash( pvec3(0.0,0.0,0.0) ); vec3 gb hash( pvec3(1.0,0.0,0.0) ); vec3 gc hash( pvec3(0.0,1.0,0.0) ); vec3 gd hash( pvec3(1.0,1.0,0.0) ); vec3 ge hash( pvec3(0.0,0.0,1.0) ); vec3 gf hash( pvec3(1.0,0.0,1.0) ); vec3 gg hash( pvec3(0.0,1.0,1.0) ); vec3 gh hash( pvec3(1.0,1.0,1.0) ); // projections float va dot( ga, w-vec3(0.0,0.0,0.0) ); float vb dot( gb, w-vec3(1.0,0.0,0.0) ); float vc dot( gc, w-vec3(0.0,1.0,0.0) ); float vd dot( gd, w-vec3(1.0,1.0,0.0) ); float ve dot( ge, w-vec3(0.0,0.0,1.0) ); float vf dot( gf, w-vec3(1.0,0.0,1.0) ); float vg dot( gg, w-vec3(0.0,1.0,1.0) ); float vh dot( gh, w-vec3(1.0,1.0,1.0) ); // interpolation return va u.x*(vb-va) u.y*(vc-va) u.z*(ve-va) u.xu.y(va-vb-vcvd) u.yu.z(va-vc-vevg) u.zu.x(va-vb-vevf) u.xu.yu.z*(-vavbvc-vdve-vf-vgvh); } varying vec2 v_uv; varying float v_y; void main(){ v_uv uv; float noise_value noise(position); float y noise_value; y pow(y,3.); vec3 in_position position; in_position.y v_y min(y35.,15.)2.; gl_Position projectionMatrixmodelViewMatrixvec4( in_position, 1.0 ); }const fragmentShader uniform float u_time; varying float v_y; varying vec2 v_uv; void main(){ gl_FragColor vec4(v_uv.x,sin(v_y100.u_time),0.5,1.); }const shaderMaterial new ShaderMaterial({ vertexShader, fragmentShader, side: DoubleSide, uniforms }) function animate() { uniforms.u_time.value clock.getElapsedTime()*0.01; requestAnimationFrame(animate) } animate()const mesh new Mesh(planeGeometry, shaderMaterial) scene.add(mesh) return mesh; }add_plane()完整源码GitHub小结本文提供魔幻山体完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库

相关新闻