Trong một trình duyệt, tốt nhất là sử dụng một spritesheet khổng lồ hoặc nhiều (10000) PNG khác nhau?


33

Tôi đang tạo một trò chơi trong jQuery, nơi tôi sử dụng khoảng 10000 gạch 32x32. Cho đến bây giờ, tôi đã sử dụng tất cả chúng một cách riêng biệt (không có bảng sprite). Một bản đồ trung bình sử dụng khoảng 2000 ô (đôi khi được sử dụng lại PNG nhưng tất cả các div riêng biệt) và phạm vi hiệu suất từ ​​ổn định (Chrome) đến hơi chậm (Firefox). Mỗi div này được định vị hoàn toàn bằng CSS. Chúng không cần được cập nhật mỗi tích tắc, ngay khi bản đồ mới được tải.

Sẽ tốt hơn cho hiệu suất khi sử dụng các phương thức spritesheet cho các div sử dụng định vị nền CSS, giống như gameQuery không?

Cảm ơn bạn trước!


3
Địa ngục bạn cần 10 000 gạch cho bản đồ? Tôi đề nghị bạn không tải lên / vẽ tất cả bản đồ về phía người dùng. Chỉ hiển thị một phần, đó là hiển thị. Khi người dùng di chuyển, tải phần tiếp theo. Cách mọi đồ họa 3D hoạt động.
Deele

Một bản đồ trung bình sử dụng 2000 ô khác nhau, hoặc chỉ 2000 tổng số ô? Làm thế nào lớn là bản đồ bạn đang tạo ra?
Nick Larsen

Bạn đã xem xét sử dụng một hoặc một vài hình ảnh lớn hơn làm nền và thực hiện phát hiện va chạm đa giác cho các ranh giới chưa?
SAHornickel

Câu trả lời:


50

Đề xuất của tôi

Quá nhiều PNG nhỏ sẽ thêm rất nhiều chi phí mạng (do kích thước của các yêu cầu HTTP, nhưng cũng là tiêu đề PNG, và, thậm chí quan trọng hơn là không có khả năng nén hiệu quả). Mặt khác, một PNG rất lớn có những nhược điểm cần phải mất một thời gian để tải và cần lưu lại vĩnh viễn trong bộ nhớ (40 megabyte cho 10.000 gạch) trong một đoạn bộ nhớ liên tục.

Tôi đề xuất nền tảng ở giữa: một số PNG có kích thước hợp lý, ví dụ 1024 gạch có kích thước 32 × 32 . Có thể được nhóm theo chủ đề (ví dụ: PNG với gạch rừng, một với gạch núi, một khác với gạch thành phố - Tôi không biết chủ đề trò chơi của bạn, nhưng bạn hiểu ý tưởng).

Lưu ý về hiệu quả bộ nhớ cache

Bởi vì hiệu quả truy cập bộ nhớ, bạn không bao giờ nên làm cho spritesheets của bạn quá rộng. Làm mờ gạch từ hình ảnh 128 × 8192 sẽ luôn nhanh hơn so với xóa từ hình ảnh 8192 × 128.

Hãy tưởng tượng bạn muốn làm mờ ô đầu tiên trong ảnh 8192 × 128. Để đơn giản, giả sử 1 pixel là 1 byte. Hai dòng pixel đầu tiên được trình bày theo cách này (các ô chứa số byte của chúng trong bộ nhớ):

┌────┬────┬───┬────┬──────────┬─────┐
  0   1 │...│ 31    ....    8191 1st line of pixels: bytes 0 to 8191
├────┼────┼───┼────┼──────────┼─────┤
81928193│...│8223   ....   16383 2nd line of pixels: bytes 8192 to 16383
├────┼────┼───┼────┼──────────┼─────┤
 ..  .. │...│ ..    ....    ... 

Vì vậy, để làm mờ dòng đầu tiên của tiêu đề đầu tiên, công cụ trình duyệt sẽ truy xuất byte 0tới31 . Để blit các dòng thứ hai , nó sẽ lấy byte 8192để8223 , và cứ thế cho đến dòng 32 byte nơi 253952để253983 được lấy ra.

Tổng số byte được xử lý sẽ là 32 × 32. Tuy nhiên, tổng phạm vi bộ nhớ là hơn 253984 byte. Trên một CPU hiện đại, điều này có nghĩa là 32 hoặc 33 bộ nhớ cache . Ngược lại, nếu hình ảnh là 128 × 8192, phạm vi bộ nhớ sẽ chỉ là 4000 byte, có nghĩa là không quá hai quầy lưu trữ bộ đệm.

Bởi vì CPU ngày nay rất nhanh, bộ nhớ cache rất đắt và treo tính toán. Vì vậy, theo lý thuyết, ít nhất là sử dụng hình ảnh 128 × 8192 thay vì hình ảnh 8192 × 128 có khả năng nhanh gấp 8 lần. Trong thực tế, điều này sẽ phụ thuộc vào cách thực hiện quá trình làm mờ: có thể chính động cơ bên dưới sẽ chia hình ảnh thành các ô để giảm sự cố.

Điều này không dễ để giải thích chính xác và tôi không mong đợi sẽ giải thích nhiều. Tôi hy vọng nó có ý nghĩa!


4
"Cũng lưu ý rằng vì hiệu quả truy cập bộ nhớ, bạn không bao giờ nên tạo ra các spritesheets của mình quá rộng. Làm mờ các hình ảnh từ hình ảnh 128 × 8192 sẽ luôn nhanh hơn việc xóa từ hình ảnh 8192 × 128." - tò mò tốt đẹp, bạn sẽ giải thích? :)
Grimshaw

@DevilWithin: Tôi đã cố gắng giải thích vấn đề; cho tôi biết nếu tôi đủ rõ ràng!
sam hocevar

Các công cụ hiệu quả bộ nhớ cache là hấp dẫn. Bạn có bất kỳ con số nào về sự khác biệt này liên quan đến tốc độ khung hình không?
Gregory Avery-Weir

Cho dù đó là một vấn đề, có vẻ như việc triển khai cụ thể, nhưng nếu API như OpenGL hành động theo kết cấu theo cách đó, thì điều quan trọng là phải xem xét điều đó, cảm ơn :)
Grimshaw

2
@DevilWithin: những gì tôi viết chỉ có giá trị cho CPU - GPU, song song ồ ạt, có các cài đặt bộ đệm rất khác nhau và sẽ lưu trữ kết cấu bằng định dạng bên trong của chính nó, được tối ưu hóa cho truy cập ngẫu nhiên. Đây là lý do tại sao kết cấu vuông, sức mạnh của hai được khuyên dùng trong OpenGL và tôi cũng sẽ tuân theo quy tắc đó cho các ô.
sam hocevar

5

Một spritesheet khổng lồ (có khả năng) sẽ cung cấp cho bạn hiệu suất tốt hơn, đơn giản vì một trong những nguyên nhân lớn nhất của độ trễ là chuyến đi khứ hồi từ yêu cầu trình duyệt đến máy chủ đến trình duyệt. 10.000 cuộc gọi HTTP sẽ mất nhiều thời gian hơn nhiều so với 1 cuộc gọi HTTP trả về một tệp lớn hơn 10.000.

Có thể có những thứ khác bạn có thể sử dụng để giảm độ trễ, tùy thuộc vào cấu trúc của trò chơi và HTML bạn đang tạo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.