Three.js 中国旗帜教程
中国旗帜 ·China Flag· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么RawShaderMaterial手写完整 GLSL含 projectionMatrix 等高细分BoxGeometry当旗面多频率sin叠加 Z 向波浪 杆边xFactor衰减vDark传递位移量做片元明暗效果说明本案例演示中国旗帜效果基于 WebGL 实现「中国旗帜」可视化效果附完整可运行源码核心用到 RawShaderMaterial、OrbitControls。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念顶点波浪float xFactor clamp((modelPosition.x 1.25) / 2.0, 0.0, 2.0);float vWave sin(modelPosition.xuFrequency.x - uTime)xFactor * uStrength; vWave sin(modelPosition.yuFrequency.y - uTime)xFactoruStrength0.5; modelPosition.z vWave;xFactor让靠近旗杆x 较小顶点几乎不动。片元明暗textColor.rgb * vDark 0.85;波浪隆起处vDark较大颜色略亮/略暗形成褶皱感。RawShaderMaterial需自行声明attribute/uniform mat4 projectionMatrix等不自动注入 Three chunk。实现步骤TextureLoader 加载国旗 JPGBoxGeometry(3, 2, 0.025, 64, 64) 高细分uniformsuTime、uFrequency、uStrength、uTextureanimate 里uTime 0.06代码要点import * as THREE from threeimport { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)camera.position.set(0.5, -0.5, 3)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.clientHeightcamera.updateProjectionMatrix()}const flagTexture new THREE.TextureLoader().load(GLOBAL_CONFIG.getFileUrl(images/chinaFlag.jpg))const flagMaterial new THREE.RawShaderMaterial({vertexShader:uniform mat4 projectionMatrix; uniform mat4 modelMatrix; uniform mat4 viewMatrix; uniform vec2 uFrequency; uniform float uTime; uniform float uStrength; attribute vec3 position; attribute vec2 uv; varying float vDark; varying vec2 vUv; void main() { vec4 modelPosition modelMatrix * vec4(position, 1.0); float xFactor clamp((modelPosition.x 1.25) / 2.0, 0.0, 2.0); float vWave sin(modelPosition.xuFrequency.x - uTime )xFactor * uStrength ; vWave sin(modelPosition.yuFrequency.y - uTime)xFactoruStrength0.5; modelPosition.y sin(modelPosition.x2.0 uTime0.5)0.05xFactor; modelPosition.z vWave; vec4 viewPosition viewMatrix * modelPosition; vec4 projectedPosition projectionMatrix * viewPosition; gl_Position projectedPosition; vUv uv; vDark vWave; },fragmentShader:precision mediump float; varying float vDark; uniform sampler2D uTexture; varying vec2 vUv; void main(){ vec4 textColor texture2D(uTexture, vUv); textColor.rgb * vDark 0.85; gl_FragColor textColor; },side: THREE.DoubleSide,uniforms: { uFrequency: { value: new THREE.Vector2(3, 3) }, uTime: { value: 0 }, uTexture: { value: flagTexture }, uStrength: { value: 0.2 } }})const flagGeometry new THREE.BoxGeometry(3, 2, 0.025, 64, 64)const flagMesh new THREE.Mesh(flagGeometry, flagMaterial)scene.add(flagMesh)animate()function animate() {flagMaterial.uniforms.uTime.value 0.06renderer.render(scene, camera)requestAnimationFrame(animate)}完整源码GitHub小结本文提供中国旗帜完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库