首页水波纹效果实现原理

预计阅读时间: 3 分钟

网站首页的背景水波纹效果实现的细节。

实现原理概述

水波纹效果的实现主要基于以下几个核心技术:

  1. 多Pass渲染系统
  2. 水波物理模拟
  3. 光照效果计算
  4. 折射效果处理
  5. 实时交互系统

以下是技术的具体实现。

多Pass渲染系统

水波纹效果使用了乒乓缓冲(Ping-Pong Buffer)技术,通过多个渲染通道来更新和传递水波状态。这种技术允许我们在不同的渲染通道之间保持和更新水波的状态信息,从而实现动态的波纹效果。

顶点着色器

顶点着色器的主要职责是处理基础的顶点变换:

1#version 300 es
2precision mediump float;
3in vec3 aVertexPosition;
4in vec2 aTextureCoord;
5uniform mat4 uMVMatrix;
6uniform mat4 uPMatrix;
7out vec2 vTextureCoord;
8
9void main() {
10    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0f);
11    vTextureCoord = aTextureCoord;
12}

水波物理模拟

水波的物理模拟主要通过法线贴图(Normal Mapping)技术实现。通过计算相邻像素的高度差来生成水面法线,从而模拟水波的传播效果。

法线计算

1vec3 calculateNormal(sampler2D tex, vec2 uv) {
2    // 控制水波强度和步长的参数
3    float stengthScale = mix(3.f, 7.f, 0.38f);
4    float stepScale = mix(1.f, 3.f, 0.38f);
5    float strength = mix(1.f, stengthScale, 0.77f);
6    float stepSize = mix(1.f, stepScale, 0.77f);
7    
8    // 采样相邻像素计算法线
9    float step = stepSize / 1080.f;
10    float left = texture(tex, uv + vec2(-step, 0.0f)).r;
11    float right = texture(tex, uv + vec2(step, 0.0f)).r;
12    float top = texture(tex, uv + vec2(0.0f, -step)).r;
13    float bottom = texture(tex, uv + vec2(0.0f, step)).r;
14    
15    // 计算法线向量
16    vec3 normal;
17    normal.x = (right - left) * strength;
18    normal.y = -(bottom - top) * strength;
19    normal.z = -1.0f;
20    return normalize(normal);
21}

光照效果

实现了完整的Blinn-Phong光照模型,包含环境光、漫反射和高光三个组成部分。

1vec4 getColor(vec2 uv) {
2    vec4 color = drawRipple(uv);
3    vec3 normal = color.rgb;
4    
5    // 计算光照方向和视角方向
6    vec3 lightDir = normalize(LIGHT_POS - vec3(uv, 0.0f));
7    vec3 viewDir = normalize(VIEW_POS - vec3(uv, 0.0f));
8    vec3 halfwayDir = normalize(lightDir + viewDir);
9    
10    // 计算漫反射和高光
11    float diff = max(dot(normal, lightDir), 0.0f);
12    float spec = pow(max(dot(normal, halfwayDir), 0.0f), SHININESS);
13    
14    // 合成最终光照效果
15    vec3 ambient = vec3(0.1f);
16    vec3 diffuse = vec3(0.9f) * diff;
17    vec3 specular = vec3(SPECULAR) * spec;
18    vec3 lighting = ambient + diffuse + specular;
19    
20    // 使用法线扰动UV坐标,创建水波折射效果
21    vec2 distortedUV = uv + normal.xy * 0.1f;
22    vec4 texColor = texture(uTexture, distortedUV);
23    vec3 finalColor = texColor.rgb * lighting;
24    return vec4(finalColor, 1.0f);
25}

折射效果

水面的折射效果通过扰动纹理采样坐标实现:

1vec2 distortedUV = uv + normal.xy * 0.1f;
2vec4 texColor = texture(uTexture, distortedUV);

这种扰动创造了水波折射的视觉效果,使底层纹理产生真实的扭曲变形。

交互系统

水波纹效果支持实时交互,通过鼠标输入来创建水波:

1float circle(vec2 uv, vec2 pos, float rad) {
2    float d = length(pos - uv) - rad;
3    float t = clamp(d, 0.0f, 1.0f);
4    return 1.0f - t;
5}
6
7void main() {
8    vec2 uv = vTextureCoord;
9    vec4 color = getColor(uv);
10    float c = circle(uv, vec2(uMouseX, uMouseY), uMouseRadius);
11    float press = uMousePressed;
12    float force = uMouseForce;
13    if (c > 0.0f) {
14        color = mix(color, vec4(0.0f, 0.0f, 0.0f, 1.0f), c * press * force);
15    }
16    fragColor = color;
17}

可调参数

效果中提供了多个可调参数来控制水波的表现:

  • SHININESS:控制水面反射的锐利程度
  • SPECULAR:控制高光强度
  • uMouseRadius:控制交互水波的影响范围
  • uMouseForce:控制水波的强度
  • strengthstepSize:控制水波的传播特性

总结

这个水波纹效果的实现综合运用了多种图形学技术,包括:

  1. 使用乒乓缓冲实现动态更新
  2. 通过法线计算模拟水波物理特性
  3. 实现完整的Blinn-Phong光照模型
  4. 使用UV扰动创建折射效果
  5. 添加实时交互系统

通过这些技术的组合,最终实现了一个既真实又具有交互性的水波纹效果。这个效果不仅可以用于游戏或网页特效,还可以作为学习WebGL和图形学的优秀案例。