🎯 提示词

PROMPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
使用 Three.js 实现**环形着色器**,具体要求:

【核心特效】
- 极坐标变换实现环形图案
- 双层火焰环形叠加
- 鼠标控制内圆大小
- 动态噪声扰动

【场景与光照】
- 深色背景
- OrbitControls 轨道控制器
- 自定义着色器实现火焰环形效果

【交互与控制】
- OrbitControls 鼠标拖拽旋转
- 鼠标滚轮缩放
- 鼠标X轴位置控制内圆半径

【技术要求】
- Three.js 版本 (ES Module)
- 自定义 ShaderMaterial 实现极坐标变换
- GLSL 噪声函数和火焰着色
- 实时鼠标交互

📖 效果拆解

层次 视觉效果 技术实现
基础 3D平面几何体 PlaneGeometry (20×20)
核心特效 极坐标环形变换 UV坐标到极坐标的数学变换
增强细节 双层火焰效果 噪声函数叠加形成火焰
交互控制 鼠标控制内圆 iMouse uniform 实时响应

🔧 核心技术点

1. 极坐标变换

为什么需要这个技术:将笛卡尔坐标转换为极坐标,实现环形图案的基础。

GLSL
1
2
3
4
5
6
vec2 polarMap(vec2 uv, float shift, float inner) {
  uv = vec2(0.5) - uv;
  float px = 1.0 - fract(atan(uv.y, uv.x) / 6.28 + 0.25) + shift;
  float py = (sqrt(uv.x * uv.x + uv.y * uv.y) * (1.0 + inner * 2.0) - inner) * 2.0;
  return vec2(px, py);
}

2. 火焰噪声函数

为什么需要 this技术:使用分形噪声模拟火焰的随机跳动效果。

GLSL
1
2
3
4
5
6
7
8
9
10
11
12
float fire(vec2 n) {
  return noise(n) + noise(n * 2.1) * .6 + noise(n * 5.4) * .42;
}

float shade(vec2 uv, float t) {
  uv.x += uv.y < .5 ? 23.0 + t * .035 : -11.0 + t * .03;
  uv.y = abs(uv.y - .5);
  uv.x *= 35.0;
  float q = fire(uv - t * .013) / 2.0;
  vec2 r = vec2(fire(uv + q / 2.0 + t - uv.x - uv.y), fire(uv + q - t));
  return pow((r.y + r.y) * max(.0, uv.y) + .1, 4.0);
}

3. 双层颜色叠加

为什么需要这个技术:创建上下对称的双层火焰环,增强视觉效果。

GLSL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void main() {
  vec2 uv = vUv;
  float ff = 1.0 - uv.y;
  uv.x -= (iResolution.x / iResolution.y - 1.0) / 2.0;
  vec2 uv2 = uv;
  uv2.y = 1.0 - uv2.y;
  uv = polarMap(uv, 1.3, m1);
  uv2 = polarMap(uv2, 1.9, m1);

  vec3 c1 = color(shade(uv, t)) * ff;
  vec3 c2 = color(shade(uv2, t)) * (1.0 - ff);

  gl_FragColor = vec4(c1 + c2, 1.0);
}

4. 鼠标交互控制

为什么需要这个技术:让用户通过鼠标实时控制环形效果参数。

JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const { mesh, uniforms } = getShaderMesh();

function getShaderMesh() {
  const uniforms = {
    iTime: { value: 0 },
    iResolution: { value: new THREE.Vector2(1900, 1900) },
    iMouse: { value: new THREE.Vector2(0, 0) }
  };

  renderer.domElement.addEventListener('mousemove', (event) => {
    uniforms.iMouse.value.x = event.clientX;
    uniforms.iMouse.value.y = event.clientY;
  });

  // 在着色器中使用 iMouse
  float m1 = iMouse.z < 0.0001 ? 3.6 : iMouse.x * 5.0 / iResolution.x;
}

💡 调试与优化

问题类型 表现形式 解决方案
环形不居中 图案偏离中心 调整 uv.x -= (iResolution.x / iResolution.y - 1.0) / 2.0
火焰闪烁过快 动画过于剧烈 减小时间系数 t * .035
鼠标控制不灵敏 内圆变化不明显 调整 m1 的计算系数

🚀 扩展思路

  1. 多层环形:添加更多层的环形火焰
  2. 颜色渐变:实现从火焰红到星空蓝的渐变
  3. 拖尾效果:添加运动模糊的拖尾
  4. 音频响应:配合音频实现声音可视化
  5. 粒子系统:添加从环形飞出的粒子

📚 相关学习资源


©️ 版权声明

本文由 Three.js 技术提供支持,示例源码来源于 public/threeExamples/shader/ring-shader.html,仅供学习交流使用。