IRO UTSUSHI

Một ứng dụng không bao giờ yêu cầu bạn đặt tên cho cảm xúc của mình. Nhỏ màu xuống mặt nước, khuấy bằng ngón tay, và chuyển động của bàn tay bạn sẽ lưu lại thành một bức tranh duy nhất.

Đã có trên App Store
  • Ứng dụng
  • iPhone / iPad
  • Swift
  • SwiftUI
  • Metal
Tải về trên App Store

Bạn có thể làm gì

Cách xây dựng

Ứng dụng Swift + SwiftUI, viết dưới dạng App Package của Swift Playgrounds, hoàn toàn không phụ thuộc vào gói bên ngoài nào.
Mặt nước Mô phỏng chất lỏng viết bằng Metal. Trường vận tốc, phép chiếu áp suất, phép truyền tải (advection), tăng cường độ xoáy và pha trộn sắc tố đều được xử lý trên GPU.
Sắc tố Được giữ dưới dạng hạt Lagrange và chồng lớp bằng phép trộn trừ theo định luật Beer–Lambert. Vì là các hạt, chúng không bị nhòe đi theo thời gian do khuếch tán.
Hình ảnh Khúc xạ và phản chiếu gương được vẽ từ pháp tuyến tính toán bằng giải tích từ trường độ cao của mặt nước, cùng với nhiễu hạt và dithering để tránh hiện tượng dải màu (banding).
Đầu vào Lấy từ sự kiện gốc của UIKit, truyền toàn bộ các lần chạm được gộp (coalesced touches) trong một khung hình cho chất lỏng. Tối đa năm lần chạm đồng thời được ghi lại, phát lại và tính toán như các nét vẽ độc lập, mỗi ngón tay một nét.
Lưu trữ Danh sách lịch sử chỉ lưu thông tin nhẹ dưới dạng JSON; hình ảnh là một file PNG duy nhất; chuỗi thao tác chạm là dữ liệu nhị phân có độ rộng cố định được nén bằng LZFSE, mỗi bản ghi có một thư mục riêng.
Phát lại và xuất file Mặt nước được dựng lại bằng cách chạy lại mô phỏng từ các bước đã lưu. File MP4 không phải là bản ghi màn hình: các khung hình được ghép lại từ những bước đó và ghi ra ở 30 fps.
Âm thanh Được tổng hợp ngay trong ứng dụng, theo thang ngũ cung với tối đa 16 giọng. Không có file âm thanh nào.
Tự kiểm tra Vì môi trường này không thể chạy XCTest, một bộ kiểm tra tự viết (SelfChecks.swift) chạy khi khởi động ở chế độ debug để thay thế.
Mã hóa Không sử dụng mã hóa nào; câu trả lời về export compliance được đính kèm cùng ứng dụng.

Những điểm thú vị về mặt kỹ thuật

Vệt xoáy vẫn tiếp tục cuộn sau khi ngón tay đã đi qua

Phép truyền tải (advection) có thêm hiệu chỉnh MacCormack, giữ lại những xoáy nhỏ mà phép truyền tải bán-Lagrange đơn giản sẽ xóa mất. Ngón tay không đẩy nước: nó thả xuống một cặp xoáy quay ngược chiều nhau dọc theo hướng kéo, nên nước vẫn tiếp tục cuộn một lúc sau khi ngón tay đã đi qua. Mọi hệ số giảm chấn và bám theo đều được biểu diễn theo “mỗi giây”, nên chuyển động giống nhau trên thiết bị 60 Hz và thiết bị 120 Hz.

Tách “sóng nhìn thấy” khỏi “sóng làm chuyển động”

Cường độ nhìn thấy của gợn sóng và tác động của nó lên sắc tố là hai tham số riêng biệt. Hơn nữa, gợn sóng làm thay đổi trực tiếp vị trí của sắc tố, chứ không phải vận tốc của nó. Vận tốc sắc tố được kéo trở lại vận tốc dòng nước mỗi khung hình — với hằng số thời gian khoảng 0,36 giây ở những vùng đậm màu — trong khi gợn sóng tồn tại ngắn hơn thế, nên phép đo cho thấy việc cộng thêm vận tốc gần như không làm sắc tố di chuyển. Nhờ vậy, việc tinh chỉnh hình ảnh và tinh chỉnh cảm giác chạm không còn phá hỏng lẫn nhau.

Quyết định không để sắc tố hút nhau

Trước đây có một lực “kết dính” khiến sắc tố tụ lại, nhưng trạng thái ổn định duy nhất mà nó có thể đạt tới là một khối tròn: theo thời gian, mặt nước dần bị lấp đầy bởi các vòng tròn mờ đục không bao giờ tan ra được nữa. Giờ đây, viền sẫm màu kiểu màu nước được tái hiện mà không cần di chuyển bất kỳ sắc tố nào. Trường mật độ được giữ nguyên, và viền được vẽ ra từ đó như một lớp đổ bóng trên bề mặt nước, nên không có gì trong bức tranh bị đông cứng lại.

Cùng một bản ghi luôn phát lại thành cùng một bức tranh

Mô phỏng được cố định ở 60 bước mỗi giây, và mỗi bản ghi lưu lại số bước thực tế mà đầu vào của UIKit được xử lý, số bước khởi động (lead-in), cùng một tệp phụ chứa mốc thời gian Float32 và tọa độ UInt16. Khi phát lại, hệ thống tin vào các bước đã lưu này hơn là đồng hồ hệ thống. Tốc độ được đo dựa trên UITouch.timestamp, vì các chuyển động trong cùng một khung hình không thể phân biệt được bằng đồng hồ hệ thống. Các lần chạm dự đoán chỉ được dùng để ước tính tốc độ; chúng không bao giờ ảnh hưởng đến vị trí sắc tố rơi xuống.

Bên cạnh đó, SimulationEngineRegistry định tuyến rõ ràng mỗi simulationVersion đã lưu đến đúng engine tương ứng. Phiên bản 6 được đóng băng đến từng hằng số, đồng hồ và tốc độ truyền mực, và một phiên bản tương lai chưa biết sẽ không bao giờ bị âm thầm đưa vào mô phỏng mới nhất. Mục đích là để hình ảnh của một bản ghi cũ không bị dựng lại thành thứ khác chỉ vì ứng dụng được cập nhật.

Không cho xem điểm số trước

Bốn chỉ số không bị cắt ở một mức trần: chúng nằm trên một đường cong tiệm cận tới 100, nên chỉ một lần chuyển động nhanh sẽ không đạt điểm tối đa. Dù vậy, chúng vẫn mặc định bị ẩn ở màn hình kết quả. Nếu một ứng dụng từ chối xếp cảm xúc vào các từ ngữ lại mở đầu bằng những con số, thì những con số đó rốt cuộc cũng chỉ trở thành một cái nhãn mới.

Quyền riêng tư và liên hệ

IRO UTSUSHI chỉ lưu các bản ghi của bạn trên thiết bị. Ứng dụng không có đăng ký tài khoản, không quảng cáo, không phân tích sử dụng, và không có chức năng theo dõi người dùng nào. Xem chi tiết tại Chính sách quyền riêng tư của IRO UTSUSHI.

Với góp ý và báo lỗi, bạn cũng có thể liên hệ qua trang liên hệ của Sizu dev.