Kích thước hình ảnh trong Unity

Tìm hiểu về kích thước của texture/sprite trong Unity

Giới thiệu

Bạn đã từng tự hỏi mình rằng kích thước nào là phù hợp khi sử dụng trong Unity chưa?.

Kích thước hình ảnh ảnh hưởng rất nhiều đến hiệu suất của trò chơi. Sử dụng kích thước hình ảnh sai có thể dẫn đến trò chơi của bạn bị crash, out-memory hoặc giật lag

Bạn có từng nghe hoặc thấy ở đâu đó nói rằng hãy giữ kích thước của hình ảnh là bội của 4 (chia hết cho 4).

Chúng ta hãy cùng tìm hiểu xem tại sao lại cần giữ kích thước hình ảnh chia hết cho 4, và lúc nào thì không nên giữ kích thước chia hết cho 4.

Kích thước hình ảnh thích hợp làm giảm mức sử dụng memory

Kích thước hình ảnh phù hợp làm giảm dung lượng bộ nhớ được sử dụng trong trò chơi.

Bộ nhớ là nơi lưu trữ tạm thời dữ liệu trò chơi và tất nhiên rồi nó không phải là vô hạn.

Khi bạn phát triển trò chơi cho mobile bạn sẽ cần lưu ý:

  • Bộ nhớ được sử dụng bởi các ứng dụng, trò chơi
  • Bộ nhớ được sử dụng bởi hệ điều hành
  • Bộ nhớ được sử dụng bởi các device khác

Tổng của chúng không được vượt qua dung lượng bộ nhớ của thiết bị. nếu vượt quá trò trơi sẽ bị buộc dừng bởi hệ điều hành (crash)

Nói cách khác sử dụng bộ nhớ càng thấp càng tốt. Texture/Sprite mà là số hai thì không ai là số một về yếu tố tiêu thụ bộ nhớ trong phát triển trò chơi. Trò chơi sử dụng rất nhiều hình ảnh, vì vậy cần giảm mức tiêu thụ bộ nhớ của hình ảnh càng nhiều càng tốt.

Cách để làm được điều đó đó là giảm kích thước của hình ảnh hay nén hình ảnh (Texture Compressed)

Thuật ngữ “Texture Compressed” dùng để miêu tả hình ảnh tương ứng với các đơn vị tính toán (GPU) của hệ điều hành (PC, Android, iOS)

Nhưng cụ thể Mobile sử dụng ASTC, ETC2

PC sử dụng DXT5

Ví dụ: Hình ảnh có chiều rộng x chiều cao là 2048x2048 có dung lượng khi không nén là 16mb

Khi sử dụng định dạng nén là ETC2 dung lượng giảm còn 4mb

Dung lượng ở đây là dung lượng bộ nhớ sử dụng, như bạn thấy kích thước nó đã giảm 25%

Tuy nhiên chúng có điều kiện sử dụng (như là tuân theo nguyên tắc trao đổi đồng giá)

Điều kiện về kích thước hình ảnh

Để sử dụng định dạng nén ETC2 chúng ta cần chiều rộng và chiều cao hình ảnh là bội của 4

Ví dụ như :

  • 128x40
  • 100x100
  • 160x64

Vào khoảng những năm 2014 thời mà GPU trên điện thoại còn rất yếu và texture compressed lúc bấy giờ yêu cầu chiều rộng và chiều cao là bội của 2 Nhưng những bước tiến vượt bậc về công nghệ và kỹ thuật của GPU điều kiện là bội của 2 dần bị thay thế bằng bội của 4

Ngoài ra cũng xuất hiện các định dạng nén cho phép hình ảnh có kích thước tùy ý.

Mặt khác kích thước hình ảnh thêm vào Unity phụ thuộc vào việc nó có nằm trong Sprite Atlas hay không.

Sprite Atlas

Sprite Atlas là một asset nó tác dụng gom, hợp nhất nhiều Sprite thành một Sprite duy nhất

Như bạn thấy MaxTextureSize đang là 2048 là bội của 4. Bất kể kích thước của các sprite bên trong là bao nhiêu nó không ảnh hưởng đến kích thước tổng thể của atlas. Nếu sprite vượt quá MaxTextureSize một atlas mới sẽ được thêm vào

Nên sử dụng định dạng nén nào?

Theo như tài liệu của Unity

The Unity Editor can import texture source files with a number of common formats, such as JPEG or PNG. However, GPUs do not use these formats at runtime; instead, they use different, specialized compression formats that are optimized for memory usage and speed of sampling operations.

Ở đây chúng ta sẽ chia định dạng nén thành các loại như sau:

  • Mặc định: RGBA 32 bit (không nén)
  • DXT
  • PVRTC
  • ETC
  • ASTC

DXT

Là định dạng nén cơ bản nhất, nó dụng định dạng khối (block) 4x4 để cố định 4 bpp (bit per pixel) để mã hóa từng khối RGB

PVRTC

Sử dụng trên các thiết bị iOS, nó có 2 lựa chọn là sử dụng 4bpp hoặc 2bpp để biểu diễn từng khối RGB, sử dụng 2bpp để giảm kích thước nén nhiều hơn PVRTC2 là phiên bản nâng cấp của PVRTC nó giảm kích thước nén trên cùng một diện tích

OpenGL ES 2.0

ETC là một phần mở rộng có sẵn của OpenGL 2.0, tuy nhiên có một nhược điểm cản trở việc nó được sử dụng rộng rãi, nó chỉ là một phần mở rộng chứ không phải một phần bắt buộc cần có của OpenGL 2. Nó không hỗ trợ kênh alpha, nó chỉ cung cấp một tùy chọn sử dụng 4bpp để mã hóa từng khối RGB

OpenGL ES 3.0

Là phiên bản tiếp theo của OpenGL ES 2.0, định dạng nén ETC được cải tiến thành ETC2 và được sử dụng như một quy chuẩn chung với khả năng tương thích ngược. Nó đã hỗ trợ kênh alpha đầy đủ giống như DTX5/3 (8bpp), nó cũng hỗ trợ định dạng EAC hỗ trợ dữ liệu dạng đơn kênh (1 kênh R, 2 kênh RB) ETC2 cũng hỗ trợ sRGB, nó cũng cung cấp chất lượng nén tốt hơn ở cùng tốc độ bit so với những định dạng khác Nhược điểm lớn nhất của nó là tốc độ nén chậm

ASTC

Đây là định dạng nén được đề xuất cho các thiết bị Android, iOS được sản xuất sau năm 2015 trở đi. Các thiết bị cũ hơn chỉ hỗ trợ ETC/ETC2 ASTC sử dụng các khối với nhiều dạng kích thước khác nhau để mã hóa RGB. Điểm đặc biệt của ASTC đó là nó sử dụng cố định 128 bit cho mỗi block, mỗi texture sẽ có kích thước khác nhau để đặt vừa 128 bit đó. Nó có thể nén hầu hết các loại texture

Một điều nữa là ASTC sử dụng phương pháp encoding endpoint, weighting, và một số phương pháp khác chọn trên mỗi block chứ không phải trên toàn bộ texture, do đó tốc độ mã hóa sẽ nhanh hơn để phân bổ hết 128 bit để cải thiện chất lượng mỗi block. Điều này giúp chất lượng hình ảnh tốt hơn so với các định dạng nén khác ngay cả khi sử dụng các chế độ nén cao hơn

Trong Unity nó có những tỉ lệ nén như sau :

BlockSize BitPerPixel
4x4 8.0
5x5 5.12
6x6 3.56
8x8 2.0
10x10 1.28
12x12 0.89

Đối với hầu hết các trường hợp nên sử dụng ASTC 6x6 block để cân bằng giữa chất lượng và kích thước hoặc 8x8 block nếu muốn giảm kích thước trong những trường hợp không quá quan trọng chất lượng hình ảnh

Lượt nghé thăm