🎯 提示词

PROMPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
使用 Three.js 实现【程序化草地效果】,具体要求:

【核心特效】
- 程序化草叶生成
- 风吹动画效果
- 云影投影
- 颜色渐变

【场景与光照】
- 天空盒背景
- 自发光草叶

【交互与控制】
- OrbitControls 轨道控制器

【技术要求】
- Three.js 最新版本
- 自定义 BufferGeometry
- ShaderMaterial 自定义着色器
- 纹理驱动的云影


📖 效果拆解

层次 视觉效果 技术实现
基础 大量草叶 自定义 GrassGeometry
核心特效 风吹动画 顶点着色器波浪函数
颜色 绿色渐变 基于高度的颜色混合
光影 云影效果 纹理偏移模拟

🔧 核心技术点

1. 程序化草叶生成

使用极坐标随机分布草叶,并计算每个草叶的顶点。

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class GrassGeometry extends THREE.BufferGeometry {
  constructor(size, count) {
    super();
    const positions = [];
    const uvs = [];
    const indices = [];
    
    for (let i = 0; i < count; i++) {
      const radius = (size / 2) * Math.random();
      const theta = Math.random() * 2 * Math.PI;
      const x = radius * Math.cos(theta);
      const y = radius * Math.sin(theta);
      
      const blade = this.computeBlade([x, 0, y], i);
      positions.push(...blade.positions);
      indices.push(...blade.indices);
    }
    
    this.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
    this.setIndex(indices);
  }
}

2. 风吹动画

在顶点着色器中根据顶点高度添加波浪效果。

GLSL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
float wave(float waveSize, float tipDistance, float centerDistance) {
  bool isTip = (gl_VertexID + 1) % 5 == 0;
  float waveDistance = isTip ? tipDistance : centerDistance;
  return sin((uTime / 500.0) + waveSize) * waveDistance;
}

void main() {
  vPosition = position;
  
  // 云影移动
  vUv.x += uTime * 0.0001 * offsetX;
  vUv.y += uTime * 0.0001 * offsetY;
  
  if (vPosition.y < 0.0) {
    vPosition.y = 0.0;
  } else {
    vPosition.x += wave(uv.x * 10.0, 0.3, 0.1);      
  }
  
  gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1.0);
}

3. 草叶颜色计算

基于高度和云影纹理计算最终颜色。

GLSL
1
2
3
4
5
vec3 green = vec3(0.2, 0.6, 0.3);
vec3 color = mix(green * 0.7, green, vPosition.y);
color = mix(color, texture2D(uCloud, vUv).rgb, 0.4);
float lighting = normalize(dot(vNormal, vec3(10)));
gl_FragColor = vec4(color + lighting * 0.03, 1.0);

💡 调试与优化

问题类型 表现形式 解决方案
性能问题 大量草叶帧率下降 减少草叶数量或使用 LOD
草叶穿透 草叶穿过地面 限制底部顶点Y坐标为0
风吹效果不自然 所有草叶同步摆动 添加随机相位偏移
颜色单调 草叶颜色统一 增加颜色随机变化

🚀 扩展思路

变体效果 核心改动 难度
动态风向 添加 GUI 控制风向和强度 ⭐⭐
季节性变化 添加颜色随季节变化 ⭐⭐
交互踩踏 添加鼠标交互压弯草叶 ⭐⭐⭐
草地纹理 添加地面纹理 ⭐⭐

本文档由 ThreeLab 编辑整理,如需转载,请注明出处。