You are currently viewing Ultra-Water cho three.js: đại dương FFT chạy hơn 200 fps kèm sóng vỗ bờ

Ultra-Water cho three.js: đại dương FFT chạy hơn 200 fps kèm sóng vỗ bờ

Có một kiểu demo three.js mà ai từng viết cũng biết: mặt nước phẳng, vài gợn sóng sine, phản chiếu bầu trời bằng cube map, xong. Nhìn ổn ở ảnh thumbnail, vào gần thì lộ ngay. Ultra-Water là repo đi ngược hướng đó, làm nước cho nghiêm túc, với FFT, caustics, foam và cả vật lý nổi.

Repo này làm gì, giải quyết vấn đề gì

Ultra-Water là ocean renderer real-time cho three.js, chạy trên WebGL2. Nó không chỉ vẽ mặt nước. Nó mô phỏng phổ sóng bằng FFT kiểu Tessendorf, dựng shore breakers (sóng vỗ bờ), foam theo Jacobian, caustics dưới nước, render cả cảnh vật dưới mặt nước, và buoyancy cho vật thể nổi. Repo kèm luôn một demo island scene để mở lên xem ngay.

Vấn đề nó giải quyết khá rõ: nếu bạn muốn một cảnh biển trong browser mà không phải tự viết toàn bộ pipeline từ đầu, đây là một điểm xuất phát đầy đủ. Phần sóng dùng 4 cascade FFT kích thước 600 / 85 / 12 / 2.1 m, xếp trong một atlas 256×1024, mỗi tầng Stockham IFFT là một MRT draw. Cascade 2.1 m là dải capillary, chỉ lấy slope chứ không lấy displacement. Gió thì JONSWAP wind sea cộng swell, directional spreading cos-2s. Nghe thì lắm thuật ngữ, nhưng ý chính là: sóng có năng lượng đúng vật lý, không phải ngẫu nhiên cho đẹp.

Phần bờ biển cũng không phải trang trí. Shore breakers chạy trên eikonal travel-time field, fast sweeping từ bờ với c = √(g·depth), nên front sóng chậm lại, dồn lại và khúc xạ theo địa hình đáy. Có Green’s law, ray-tube shoaling, breaking limit 0.42 × depth, và set lớn hơn ở bờ hướng về phía swell. Đây là mấy thứ mà nếu tự làm bạn sẽ mất vài tuần đọc paper.

Vì sao repo này đang được chú ý

544 sao sau một ngày tạo (2026-10-28) là con số đáng để ý. Một phần vì demo trông tốt thật, phần khác vì README viết cực kỳ chi tiết về benchmark, đến mức tự sửa lại con số cũ của chính mình.

Điểm khác biệt nằm ở chỗ tác giả không giấu chi phí. Bảng benchmark trên RTX 3060 (Chrome, ANGLE/D3D11), 4× MSAA, bật hết tính năng, ở 1954×1692 (3.3 MP, tức số pixel của 1440p): Open ocean 3.30 ms (~303 fps), Breakers 4.17 ms (~240 fps), Lagoon 4.48 ms (~223 fps), Underwater 4.71 ms (~212 fps). Chia theo pass trong cảnh Breakers: water 1.66 ms, opaque 1.21 ms, post 0.37 ms, caustics 0.24 ms, FFT sim khoảng 0.45 ms và không phụ thuộc resolution.

Đoạn README thừa nhận các số cũ thấp hơn 2 đến 4 lần vì benchmark dùng readPixels/finish, thứ mà ANGLE không chờ. Bản mới dùng fence. Việc tự bóc phốt benchmark của mình như vậy hiếm, và nó khiến mấy con số còn lại đáng tin hơn.

Có cả profile riêng cho điện thoại. Trên OnePlus Nord 4 (Snapdragon 7+ Gen 3, Adreno 732), portrait 424×782, cả 7 cảnh đều 60 fps live, 0% missed frames, uncapped từ 95 đến 142 fps. Với setting desktop trên cùng máy đó thì tụt còn 41 đến 50 fps, mất tới một phần ba frame. Tác giả ghi rõ là máy đo lúc ấm (thermal status 1) và đang sạc USB. Chi tiết kiểu này thường không có trong README của repo demo.

Cài và chạy thử

Không có gì phức tạp, hai lệnh:

npm install
npm run dev

Mở URL localhost in ra. Chuột để orbit, điện thoại thì dùng ngón tay. Dropdown camera đổi góc chụp, mỗi góc set luôn hướng mặt trời. Panel performance ở góc trên trái hiện GPU, render size, fps, ms per frame và graph 20 giây.

Muốn đo thật thì bấm Run benchmark (hoặc benchmark (uncapped) trong settings). Nó render 300 frame liên tiếp với render loop tạm dừng, đo tới lúc GPU xong bằng fence. Màn hình đứng khoảng một giây, nên chỉ chạy khi bạn chủ động bấm. Nút Uncap FPS tắt giới hạn refresh, tối đa ba frame in flight trên GPU, còn Cap to display để quay lại.

Ép profile bằng query string nếu cần:

?mobile
?desktop

Ai nên dùng, dùng vào việc gì

Rõ nhất là dev làm web 3D cần cảnh biển cho product configurator, game browser, hay landing page có tương tác. Demo island có sẵn, thay model đảo bằng model của bạn là ra cảnh mới.

Nhóm thứ hai là người làm visualization: mô phỏng tàu thuyền, cảnh quan ven biển, hay bất cứ thứ gì cần nước có hành vi hợp lý. Buoyancy có sẵn cho 10 vật nổi trong cảnh Flotsam, chạy 4.62 ms/frame (~217 fps) trên 3060.

Nhóm thứ ba, và có lẽ là nhóm sẽ học được nhiều nhất, là người muốn đọc code để hiểu cách làm ocean rendering. Cấu trúc file tách rõ: src/water/OceanSim.js cho simulation, src/water/OceanSurface.js cho shading, shoreMap.js cho sóng bờ. Muốn hiểu glints làm sao, subsurface scatter ra sao, đọc thẳng trong đó.

Không phù hợp nếu bạn cần nước tĩnh cho ảnh render offline, hoặc dự án phải chạy trên WebGL1 hay thiết bị rất yếu. Đây là WebGL2, không có fallback.

Ưu điểm và hạn chế

Ưu điểm dễ thấy nhất là độ đầy đủ. Rất ít repo three.js làm nước có đủ FFT, foam, caustics, underwater, buoyancy trong một gói, lại còn license MIT. Benchmark minh bạch tới mức hiếm gặp. Code có comment giải thích công thức, ví dụ chỗ capillary-gravity dispersion ω² = gk + σk³/ρ, hay chỗ quantise ω về loop 300 giây để phase fp32 không trôi.

Hạn chế thì phải nói thật. Repo mới tạo ngày 2026-10-28, tức là cực non, chưa có cộng đồng, chưa có issue nào để tham khảo khi gặp lỗi. README có đoạn tự nhận là crest-foam upgrade vừa land sau lần benchmark và chưa đo lại sạch vì lúc đó có ứng dụng khác đang load GPU. Nghĩa là con số trong bảng chưa tính phần foam mới.

Tài liệu dừng ở mức README rất dài và comment trong code, không có docs site, không có API reference. Nếu bạn muốn nhúng vào project có sẵn, phải đọc code để biết cách hook. Không có topic nào trên GitHub, tìm kiếm sẽ khó.

Về license, MIT là thoáng, dùng thương mại được, chỉ cần giữ copyright notice. Nhưng vì repo quá mới, cân nhắc chuyện maintain dài hạn. Nếu tác giả bỏ giữa đường, bạn sẽ phải tự lo phần sóng FFT, mà đó không phải phần dễ.

Kết

Nếu bạn đang cần một cảnh biển tử tế trong three.js và không muốn tự viết FFT từ giấy, Ultra-Water tiết kiệm cho bạn vài tuần. Còn nếu chỉ cần mặt nước gợn nhẹ cho landing page, 4.17 ms/frame cho cảnh Breakers trên 3060 là hơi phí, dùng shader đơn giản hơn sẽ nhẹ đầu hơn. Repo ở đây: Humpalumps/Ultra-Water.

Chia sẻ bài này

TelegramXFacebookZalo
Đăng ngày 02/11/2026
Giang Na
Về tác giả: Giang Na
Người lập ra blog từ 2015 với những bài về Blogspot. Giờ tập trung vào cách đưa AI vào việc thường ngày, theo hướng thực dụng và dễ làm theo.

Giang Na

Người lập ra blog từ 2015 với những bài về Blogspot. Giờ tập trung vào cách đưa AI vào việc thường ngày, theo hướng thực dụng và dễ làm theo.