BLOG Công nghệ & Kỹ thuật

Mô Phỏng Vật Lý Trong JS (Phần 1): Lý Thuyết Toán Học & Hiệu Ứng Ripple

1. Tổng Quan & Tư Duy Mô Phỏng Vật Lý Trong JavaScript Animation

Trong phát triển Web UI/UX hiện đại, hoạt họa (Animation) không chỉ dừng lại ở các chuyển động tuyến tính hay easing curve cố định (CSS transitions, GSAP tweens). Khi muốn tái hiện các hiện tượng tự nhiên như mặt nước gợn sóng (Ripple Effect), vệt nước mưa rơi hay tương tác hạt, chúng ta cần bước vào thế giới của mô phỏng vật lý (Physics-based Simulation).

Hiệu ứng gợn sóng (Ripple Effect) mô phỏng sự lan truyền sóng trên bề mặt chất lỏng khi có tác động ngoại lực (hạt mưa rơi, con trỏ chuột di chuyển). Khi sóng lan truyền, độ cao mặt nước biến đổi làm bẻ cong các tia sáng đi qua, tạo ra hiện tượng khúc xạ ánh sáng (Light Refraction) làm biến dạng hình ảnh nền bên dưới.

Để giải quyết bài toán này trên web, chúng ta có hai tiếp cận toán học và hạ tầng kỹ thuật hoàn toàn khác nhau:

  • Phương pháp 1: Mô phỏng lan truyền sóng 2D bằng Sai phân Hữu hạn (CPU Canvas 2D) — Giải số phương trình sóng đạo hàm riêng (PDE) trên lưới pixel rời rạc. Cho phép nhiều nguồn sóng tương tác và giao thoa tự nhiên.
  • Phương pháp 2: Biến dạng tọa độ dạng lượng giác Sombrero (GPU WebGL) — Sử dụng nghiệm sóng chạy tường minh (closed-form wave equation) dạng cos(k·r - ω·t) trong GLSL Fragment Shader. Cực kỳ nhanh nhưng mang tính tuần hoàn thủ tục từ một tâm cố định.

2. Phương Pháp 1: Mô Phỏng Lan Truyền Sóng 2D trên Canvas (CPU-based)

2.1. Phương trình sóng liên tục (Continuous Wave Equation)

Bề mặt nước được mô hình hóa như một trường vô hướng độ cao u(x, y, t) phụ thuộc vào vị trí (x, y) và thời gian t. Sự lan truyền sóng tuân theo phương trình sóng 2 chiều:

∂²u / ∂t² = c² · ∇²u = c² · ( ∂²u/∂x² + ∂²u/∂y² )

Trong đó:

  • u(x, y, t): Độ cao mặt nước tại tọa độ (x, y) ở thời điểm t.
  • c: Vận tốc lan truyền của sóng trên bề mặt.
  • ∇²u: Toán tử Laplace (Laplacian) — đo độ cong cục bộ của bề mặt nước.

Ý nghĩa vật lý: Gia tốc độ cao tại một điểm tỉ lệ thuận với độ chênh lệch độ cao giữa điểm đó và trung bình các điểm xung quanh. Nếu điểm đó thấp hơn xung quanh, lực căng bề mặt sẽ kéo nó lên; nếu cao hơn, nó sẽ bị kéo xuống. Đây chính là cơ chế lan tỏa sóng tròn đồng tâm.

2.2. Rời rạc hóa bằng sai phân hữu hạn (Finite Difference Discretization)

Để máy tính xử lý trên lưới pixel rời rạc, các đạo hàm riêng được xấp xỉ bằng sai phân trung tâm (Central Difference):

Xấp xỉ đạo hàm theo thời gian: (bước thời gian Δt, u_t là khung hình hiện tại, u_{t-1} là khung hình trước):

∂²u / ∂t² ≈ ( u_{t+1}(x,y) − 2·u_t(x,y) + u_{t-1}(x,y) ) / Δt²

Xấp xỉ đạo hàm theo không gian (Laplacian 5 điểm trên lưới pixel):

∇²u ≈ ( u(x+1,y) + u(x-1,y) + u(x,y+1) + u(x,y-1) − 4·u(x,y) ) / Δx²

2.3. Điều kiện ổn định Courant & Thuật toán Hugo Elias rút gọn

Thay hai biểu thức sai phân vào phương trình sóng gốc và giải tìm độ cao ở khung hình kế tiếp u_{t+1}:

u_{t+1} = 2u_t − u_{t-1} + (c²Δt²/Δx²) · ( Σneighbors − 4u_t )

Số hạng λ = c²Δt²/Δx² được gọi là số Courant. Để sơ đồ sai phân ổn định và không bị bùng nổ nghiệm (numerical instability), λ ≤ 1. Thuật toán Hugo Elias kinh điển chọn λ = 1/2, biến đổi công thức trở nên cực kỳ tinh gọn:

u_{t+1} = (1/2) · Σneighbors − u_{t-1}

Trong mã nguồn JavaScript, công thức này được biểu diễn đơn giản như sau:

average = (rippleMap[top] + rippleMap[bottom] + rippleMap[left] + rippleMap[right]) / 2;
height  = average - rippleMap[newIdx];

Việc sử dụng 2 mảng đệm (Double-buffering) hoán đổi vai trò qua mỗi frame đóng vai trò chính là u_tu_{t-1}.

2.4. Ma sát & Suy giảm năng lượng (Damping Term)

Trong thực tế, môi trường nước có độ nhớt và ma sát không khí. Nếu giữ nguyên phương trình sóng lý tưởng, sóng sẽ dao động vĩnh viễn. Ta thêm số hạng suy giảm ma sát nhân tạo:

height -= height >> 5   // Tương đương height *= (1 - 1/32) ≈ 0.96875

Về bản chất, đây là phép xấp xỉ số hạng ma sát −γ · (∂u/∂t) trong phương trình sóng damped wave equation ∂²u/∂t² = c²∇²u − γ·(∂u/∂t), giúp sóng dập tắt dần một cách tự nhiên.

2.5. Khúc xạ ánh sáng & Dịch chuyển tọa độ UV

Trường độ cao u(x,y) không được tô màu trực tiếp mà dùng để tính toán độ dốc bề mặt (gradient). Theo định luật khúc xạ Snell, độ lệch tia sáng tỉ lệ với độ dốc bề mặt Δuv ∝ ∇u(x,y). Ta dùng độ dốc này để dịch chuyển tọa độ lấy mẫu ảnh nền, tạo ra ảo giác hình ảnh bị bẻ cong qua làn nước.


3. Phương Pháp 2: Biến Dạng Tọa Độ Lượng Giác trên WebGL (GPU-based)

3.1. Hàm Sombrero 2D & Sóng Chạy (Traveling Wave)

Hàm Sombrero 2D
Mô phỏng đồ thị hàm Sombrero 2D z(r) = sin(r)/r với các vòng sóng tròn đồng tâm biên độ suy giảm

Thay vì giải phương trình sai phân từng bước trên CPU, Phương pháp 2 áp dụng trực tiếp nghiệm dạng đóng (closed-form solution) của phương trình sóng 1D theo bán kính r = √(x² + y²). Hàm Sombrero (mũ Mexico) lý thuyết có dạng z(r) = sin(r) / r.

Trong GLSL Fragment Shader, ta sử dụng nghiệm sóng chạy tuần hoàn hình sin/cos:

vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
float cLength = length(cPos);
vec2 uv = (gl_FragCoord.xy / resolution.xy) + (cPos / cLength) * cos(cLength * 12.0 - time * 4.0) * 0.03;

3.2. Ý Nghĩa Các Thông Số Vật Lý Trong Shader

  • Số sóng k = 12.0: Quyết định bước sóng λ = 2π/k (mật độ đường gợn sóng).
  • Tần số góc ω = 4.0: Vận tốc dao động pha theo thời gian.
  • Vận tốc lan truyền v = ω/k = 4/12 = 0.33: Tốc độ sóng cuộn ra xa tâm.
  • Biên độ A = 0.03: Mức độ biến dạng tọa độ UV (cường độ khúc xạ).
  • Vector đơn vị cPos / cLength: Đảm bảo sự biến dạng UV luôn diễn ra theo hướng xuyên tâm phát xuất từ tâm sóng.

4. Bảng So Sánh & Hướng Đi Nâng Cấp (Hybrid Ping-Pong WebGL)

Tiêu chíPhương pháp 1 (Canvas 2D CPU)Phương pháp 2 (WebGL GLSL GPU)
Nền tảng toán họcPDE sóng 2D, giải số bằng sai phân hữu hạn (Hugo Elias)Nghiệm sóng chạy tường minh A·cos(kr − ωt)
Môi trường xử lýCPU (Main Thread JavaScript)GPU (Fragment Shader)
Tính tương tácGiao thoa đa điểm chân thực, sóng phản xạSóng thủ tục tuần hoàn từ tâm cố định
Hiệu năngGiảm khi màn hình lớn O(width × height)Cực mượt 60+ FPS ở độ phân giải 4K/8K

Ở Phần 2, chúng ta sẽ bắt tay vào hiện thực hóa mã nguồn chi tiết cho cả 2 phương pháp, đồng thời tìm hiểu kỹ thuật WebGL Ping-Pong Framebuffer Simulation — kết hợp ưu điểm tương tác chân thực của Phương pháp 1 và tốc độ xử lý phần cứng của Phương pháp 2.

Tìm kiếm bài viết

Chia sẻ bài viết