★AppGiaiTri Đăng nhập
Công nghệ đằng sau

Trình duyệt vẽ 60 hình mỗi giây thế nào: vòng lặp khung hình, canvas và ngân sách điểm ảnh

Vì sao màn hình 120Hz làm ứng dụng ẩu chạy như tua nhanh, bước thời gian cố định giữ bóng bay đúng tốc độ trên mọi máy, và vì sao số điểm ảnh — không phải số hình — mới là thứ làm giật.

Trình duyệt vẽ 60 hình mỗi giây thế nào: vòng lặp khung hình, canvas và ngân sách điểm ảnh

Một cú đánh bóng trên màn hình điện thoại trông liền mạch như phim. Thật ra nó là hàng chục bức tranh tĩnh nối nhau, mỗi bức được vẽ lại từ đầu trong chưa tới hai mươi phần nghìn giây. Bài này mở nắp chiếc máy vẽ đó: trình duyệt biết lúc nào phải vẽ, vẽ bằng gì, vì sao có lúc giật, và những quyết định rất cụ thể mà người làm ứng dụng phải đưa ra để hình ảnh mượt trên cả chiếc điện thoại cũ lẫn chiếc máy đời mới nhất. Ví dụ lấy từ mã thật của AppGiaiTri.

Hai mươi phần nghìn giây cho một bức tranh

Màn hình điện thoại phổ thông làm tươi 60 lần mỗi giây. Chia ra, mỗi khung hình có khoảng 16,7 phần nghìn giây (dân trong nghề gọi là “ngân sách khung hình”). Trong khoảng đó, ứng dụng phải làm xong ba việc: đọc thao tác của người dùng, tính xem mọi vật đã di chuyển tới đâu, rồi vẽ lại toàn bộ cảnh. Làm không kịp thì màn hình đành giữ bức tranh cũ thêm một nhịp — mắt người thấy đó là “khựng”.

Điều ít người để ý: mắt không khó chịu vì số khung hình thấp, mà vì số khung hình không đều. Một ứng dụng chạy đều đặn 30 hình mỗi giây trông dễ chịu hơn một ứng dụng lúc 60 lúc 40. Vì thế mục tiêu của người làm không phải là “càng nhanh càng tốt”, mà là “không bao giờ trễ hạn”.

Ai bấm chuông báo giờ vẽ

Trình duyệt có một cơ chế tên là requestAnimationFrame — tạm dịch là “gọi tôi khi sắp vẽ khung kế tiếp”. Ứng dụng đăng ký một hàm, trình duyệt gọi hàm đó đúng lúc màn hình chuẩn bị làm tươi, kèm theo một mốc thời gian chính xác. Cách này tốt hơn hẳn kiểu cũ “cứ 16 phần nghìn giây chạy một lần” vì hai lý do:

  • Nó khớp nhịp với màn hình thật, nên không có chuyện vẽ hai lần trong một nhịp hoặc bỏ lỡ một nhịp vì lệch pha.
  • Khi người dùng chuyển sang ứng dụng khác hoặc tắt màn hình, trình duyệt ngừng gọi — pin không bị hao vô ích.

Nhưng chính cái “khớp với màn hình thật” lại gây rắc rối: màn hình không phải chiếc nào cũng 60. Máy đời mới làm tươi 90, 120 lần mỗi giây; máy đang tiết kiệm pin có thể tụt xuống thấp hơn. Nếu ứng dụng cứ mỗi lần được gọi lại cho quả bóng bay thêm một đoạn cố định, thì trên máy 120 lần mỗi giây quả bóng bay nhanh gấp đôi. Lỗi kinh điển của người mới làm: máy mình thấy đúng, máy bạn thì “như tua nhanh”.

Tách “tính toán” khỏi “vẽ”: bước thời gian cố định

Cách chữa mà AppGiaiTri dùng — và phần lớn người làm lâu năm dùng — là tách hai nhịp ra. Nhịp tính toán cố định đúng 60 lần mỗi giây, bất kể màn hình. Nhịp vẽ thì chạy theo màn hình. Giữa hai nhịp có một “thùng chứa thời gian”.

  1. Mỗi lần trình duyệt gọi, ứng dụng đo thời gian đã trôi qua từ lần trước và đổ vào thùng.
  2. Chừng nào thùng còn đủ một phần sáu mươi giây, ứng dụng tính một bước (di chuyển bóng, kiểm va chạm, cập nhật đối thủ) rồi rút phần đó ra khỏi thùng.
  3. Phần lẻ còn sót trong thùng được dùng để vẽ: nếu còn nửa bước, vật thể được vẽ ở vị trí nội suy giữa hai bước gần nhất.

Kết quả: trên máy 120 lần mỗi giây, cứ hai lần vẽ mới có một bước tính; trên máy tụt xuống 40, có lần phải tính hai bước rồi mới vẽ. Quả bóng bay cùng một tốc độ ở mọi máy, và — quan trọng không kém — mọi phép tính vật lý cho ra đúng một kết quả với cùng một chuỗi thao tác. Điều này về sau cho phép kiểm lại lượt chơi, và cho đối thủ máy “nhìn trước” đường bóng (có bài riêng về chuyện này).

Hai cái chốt an toàn mà sách ít nhắc

Lõi vẽ dùng chung của AppGiaiTri (tệp engine.js) có hai dòng nhìn qua tưởng thừa, nhưng mỗi dòng là một bài học đã trả giá:

  • Thời gian trôi qua bị chặn trần một phần tư giây. Khi điện thoại khựng vì một thông báo bật lên, hay người dùng kéo thanh thông báo xuống rồi thả, có thể một nhịp kéo dài nửa giây. Không chặn, thùng thời gian đầy ắp, ứng dụng cố tính một loạt bước để “đuổi kịp” — quả bóng xuyên qua vợt như bóng ma.
  • Mỗi lần vẽ tính tối đa năm bước. Nếu máy yếu tới mức tính một bước mất lâu hơn một phần sáu mươi giây, càng cố đuổi càng tụt lại, cuối cùng đứng hình hẳn — người trong nghề gọi là “vòng xoáy chết”. Chặn ở năm bước chấp nhận cho mọi thứ chậm lại một chút thay vì treo máy.

Chuyển tab hay khoá màn hình thì vòng lặp tự dừng, quay lại thì đặt lại đồng hồ — không có chuyện mở máy ra thấy đối thủ đã tự ghi mười điểm.

Vật chuyển động nhanh cần bước nhỏ hơn

Một phần sáu mươi giây nghe ngắn, nhưng quả bóng tennis bay 30 mét mỗi giây sẽ đi được nửa mét trong một bước — đủ để “nhảy qua” đỉnh lưới mà không chạm. Trong Giao Đấu, mỗi bước tính của quả bóng được chia nhỏ thêm bốn lần, tức bóng được kiểm va chạm 240 lần mỗi giây, trong khi người chơi và đối thủ vẫn cập nhật 60 lần. Chỉ tốn công cho đúng vật cần.

Canvas: một tấm bảng trắng vẽ lại từ đầu

Các ứng dụng của AppGiaiTri vẽ lên một thẻ gọi là canvas — tấm vải vẽ của trình duyệt. Khác với trang web thông thường (trình duyệt tự nhớ nút ở đâu, chữ ở đâu), canvas không nhớ gì: mỗi khung hình, ứng dụng xoá sạch rồi ra lệnh vẽ lại từng thứ — trời, sân, lưới, người, bóng, hiệu ứng, chữ. Nghe tốn kém, nhưng với cảnh động liên tục đây lại là cách nhanh nhất.

Lệnh vẽ đi qua nhiều tầng: ứng dụng gọi “tô hình tròn màu cam”, trình duyệt chuyển thành lệnh cho card đồ hoạ, card đồ hoạ tô từng điểm ảnh. Trên máy hiện nay, bước cuối gần như luôn được card đồ hoạ làm hộ. Điều đó có nghĩa là thứ thường khiến canvas chậm không phải số hình vẽ, mà là tổng số điểm ảnh phải tô.

Bẫy lớn nhất: màn hình càng nét, càng dễ giật

Điện thoại hiện đại có mật độ điểm ảnh cao: một “điểm” mà trang web thấy thực chất là 2×2 hoặc 3×3 điểm ảnh vật lý. Muốn hình sắc nét, canvas phải to đúng bằng số điểm ảnh thật. Làm phép tính với một chiếc iPhone cỡ phổ biến: màn hình 390×844 điểm, mật độ gấp 3 → gần 3 triệu điểm ảnh mỗi khung, 60 lần mỗi giây. Đó là con số đủ làm máy nóng lên sau vài phút, dù mắt người gần như không phân biệt được với mật độ thấp hơn một chút.

Lõi vẽ của AppGiaiTri xử lý bằng một ngân sách điểm ảnh: tối đa khoảng 2,4 triệu điểm ảnh cho mỗi khung, và mật độ không vượt quá 2,5 lần. Với chiếc iPhone ở trên, canvas được vẽ ở mức khoảng 2,1 triệu điểm ảnh — giảm khoảng 30% khối lượng tô, mắt thường không nhận ra. Máy tính bảng màn hình lớn tự giảm mật độ nhiều hơn; điện thoại nhỏ được giữ nét tối đa. Người dùng chọn “hiệu ứng thấp” trong cài đặt thì mật độ về 1, và số hạt lửa, bụi, tia sáng trong mỗi vụ nổ chỉ còn một phần ba.

Kích thước logic cố định

Mọi toạ độ trong ứng dụng được tính trên một khung logic có cạnh ngắn cố định, rồi mới phóng theo màn hình thật. Nhờ vậy cú vuốt “dài 200 điểm” có cùng ý nghĩa trên mọi máy; tính bằng điểm ảnh thật thì người máy to phải vuốt dài hơn mới đánh mạnh bằng người máy nhỏ.

Những thứ làm giật mà không nằm ở phần vẽ

Nguyên nhânBiểu hiệnCách tránh
Tạo quá nhiều đối tượng tạm trong mỗi khungCứ vài giây khựng một nhịp dù cảnh không nặngBộ dọn rác của trình duyệt phải chạy thu hồi bộ nhớ; hạn chế tạo đối tượng mới bên trong vòng lặp
Đo đạc bố cục trang giữa lúc vẽKhựng khi mở menu chồng lên cảnhTách menu (trang web thường) khỏi canvas, không hỏi kích thước phần tử trong vòng lặp
Máy nóng, tự hạ xungMượt năm phút đầu, sau đó giật dầnNgân sách điểm ảnh ở trên, và tuỳ chọn hiệu ứng thấp

Hàng cuối đáng nói thêm: nhiều lời phàn nàn “ứng dụng web giật” thật ra là máy tự giảm tốc vì nóng. Đo năm phút đầu thì đẹp; người dùng thật chơi mười phút dưới nắng thì khác. Vì thế ngân sách điểm ảnh là mặc định, không phải tuỳ chọn.

Còn card đồ hoạ “thật” thì sao?

Canvas hai chiều đủ cho năm ứng dụng hiện tại: một sân, vài nhân vật, vài chục hạt hiệu ứng. Cần hàng nghìn vật thể hay thế giới ba chiều thì người làm chuyển sang giao tiếp thẳng với card đồ hoạ qua WebGL hoặc WebGPU — chuyện đó có bài riêng.

Câu hỏi thường gặp

Vì sao ứng dụng web chạy mượt trên máy này mà giật trên máy khác?

Thường do số điểm ảnh phải vẽ khác nhau rất xa giữa các máy, và do máy nóng lên thì tự giảm tốc. Ứng dụng làm kỹ sẽ giới hạn tổng số điểm ảnh mỗi khung và có tuỳ chọn hiệu ứng thấp. Nếu vẫn giật, thử tắt chế độ tiết kiệm pin và để máy nguội bớt.

Màn hình 120Hz có làm ứng dụng web chạy nhanh hơn không?

Nếu ứng dụng làm đúng thì không: hình ảnh mượt hơn nhưng tốc độ của bóng, xe hay nhân vật vẫn y như trên máy 60Hz. Ứng dụng làm ẩu, cho vật di chuyển một đoạn cố định mỗi khung hình, sẽ chạy nhanh gấp đôi trên màn hình 120Hz.

60 khung hình mỗi giây có thật sự cần không?

Với cảnh chuyển động nhanh như bóng bay hay xe chạy, 60 khung hình giúp ước lượng thời điểm chính xác hơn. Tuy vậy, độ đều quan trọng hơn con số: 30 khung hình đều đặn dễ chịu hơn 60 khung hình lúc lên lúc xuống.

Chế độ hiệu ứng thấp thay đổi những gì?

Trong các ứng dụng của AppGiaiTri, hiệu ứng thấp vẽ canvas ở mật độ điểm ảnh 1 và giảm số hạt hiệu ứng còn một phần ba. Luật chơi, tốc độ và độ khó giữ nguyên, chỉ hình ảnh bớt nét và bớt lấp lánh.

Canvas là gì?

Canvas là một vùng vẽ trong trang web mà ứng dụng tự tô từng hình, từng màu, mỗi khung hình vẽ lại từ đầu. Nó hợp với cảnh chuyển động liên tục, và phần tô điểm ảnh thường được card đồ hoạ của máy làm hộ.

Vì sao chuyển sang ứng dụng khác rồi quay lại thì mọi thứ vẫn đứng yên?

Khi trang bị ẩn, trình duyệt ngừng gọi vòng vẽ và ứng dụng chủ động tạm dừng đồng hồ. Quay lại, đồng hồ được đặt lại nên trận đấu tiếp tục đúng chỗ cũ, không bị tua nhanh để bù khoảng thời gian bạn vắng mặt.

Cần tư vấn cụ thể cho trường hợp của bạn?

Chúng tôi sẽ liên hệ trong vòng 24 giờ.

Đăng ký tư vấn ngay

Bài viết liên quan

Bạn cần hỗ trợ thêm?

Để lại thông tin, chúng tôi sẽ liên hệ trong 24 giờ.