Tối ưu hóa trò chơi XNA 2D


56

Liệu có hợp lý khi triển khai logic để bỏ qua việc hiển thị các đối tượng bên ngoài khung nhìn hay tôi không nên quan tâm đến nó và để Framework làm điều đó?

Câu trả lời:


79

Culling là một tối ưu hóa hiệu suất. Vì vậy, thật vô nghĩa khi chỉ làm điều đó vì lợi ích của nó. Bạn phải có một lý do.


GPU (không phải XNA Framework) loại bỏ các hình tam giác và pixel với tốc độ nhanh chóng. Mỗi tam giác bạn gửi phải được chuyển đổi (thông qua shader đỉnh của bạn). Sau đó, nó loại bỏ những cái mà hạ cánh màn hình. Sau đó, nó lấp đầy các hình tam giác còn lại, loại bỏ các pixel ngoài màn hình. Các pixel còn lại sau đó được vẽ vào bộ đệm phía sau (thông qua trình đổ bóng pixel của bạn).

(Khi tôi nói "sau đó" - nó thực sự làm tất cả điều này trong một đường ống song song ồ ạt.)

Vì vậy, rất hiếm và bất thường khi bạn có thể phải loại bỏ các hình tam giác riêng lẻ. Để đạt giới hạn đỉnh, bạn phải vẽ một số lượng lớn các hình tam giác vô lý. Để đạt các giới hạn tỷ lệ lấp đầy, tìm nạp kết cấu hoặc đổ bóng pixel, bạn thường cần phải có độ phức tạp cao (trong trường hợp đó, chế độ xem / loại bỏ sự thất vọng sẽ không giúp ích gì).


Vì vậy, thường có ít hoặc không có chi phí để có hình học ngoài màn hình.

Chi phí - đặc biệt là trong bối cảnh vẽ các "đối tượng" (thường là các đối tượng 3D) - thực sự là trong việc gửi các đối tượng đó đến GPU ngay từ đầu . Gửi quá nhiều đối tượng và bạn đạt giới hạn lô của mình (bạn nhận được vài nghìn * lô trên mỗi khung).

Tôi khuyên bạn nên đọc câu trả lời nàybản trình chiếu được liên kết này để biết mô tả sâu về các lô.

Bởi vì điều này, nếu bạn thực hiện loại bỏ bực bội, bạn có thể giảm số lượng lô bạn gửi cho GPU. Nếu bạn giới hạn lô - điều này có thể giúp bạn dưới giới hạn.


Bây giờ - câu hỏi của bạn là về 2D XNA - vì vậy có lẽ bạn đang sử dụng SpriteBatch. Điều này là một chút khác nhau.

Không có gì nhầm lẫn khi nó được gọi là "Sprite Batch ". Những gì nó đang làm là lấy các họa tiết bạn vẽ và làm tốt nhất có thể để gửi các họa tiết đó đến GPU theo càng nhiều đợt càng tốt bằng cách ghép chúng lại với nhau.

Nhưng SpriteBatch sẽ buộc phải bắt đầu một đợt mới nếu:

  • Bạn vẽ nhiều họa tiết hơn mức có thể vừa với một đợt (2048 họa tiết trong XNA 4)
  • Bạn thay đổi kết cấu (đây là lý do tại sao có tùy chọn sắp xếp theo kết cấu)

Vì vậy, loại bỏ là một tối ưu hóa phù hợp nếu bạn đang chạy vào cái đầu tiên. Nếu bạn đang gửi một số lượng lớn các sprite như vậy mà cuối cùng bạn có quá nhiều đợt (có lẽ bạn cũng đang sử dụng hết băng thông - nhưng tôi chắc chắn rằng bạn sẽ đạt giới hạn lô trước). Điều này thường chỉ xảy ra nếu bạn có một thế giới thực sự rộng lớn - vì vậy bạn thường có thể thoát khỏi việc loại bỏ rất đơn giản, nhanh chóng nhưng không chính xác trong trường hợp này.

Bây giờ - Nếu bạn đang vẽ với đủ các hoán đổi kết cấu để đưa bạn vượt quá giới hạn lô, rất nhiều trong số chúng thực sự nằm ngoài màn hình loại bỏ chúng sẽ đưa bạn đến giới hạn lô. Sau đó, có - loại bỏ là một tối ưu hóa sẽ làm việc.

Tuy nhiên - một tối ưu hóa tốt hơn để theo đuổi trong trường hợp này là sử dụng kết cấu nền (hay còn gọi là tấm sprite). Điều này cho phép bạn giảm số lượng hoán đổi kết cấu và do đó các đợt - bất kể những gì trên màn hình hoặc tắt. (Đây là lý do chính mà bạn có thể chỉ định một hình chữ nhật nguồn cho các họa tiết của mình.)


(Như mọi khi: đây là lời khuyên về tối ưu hóa hiệu suất. Vì vậy, bạn nên đo lường và hiểu hiệu suất của chính trò chơi của mình và giới hạn nào bạn đang đạt được, trước khi dành nỗ lực để thêm tối ưu hóa.)


5
+1 Để đề cập đến việc không nên loại bỏ chỉ vì lợi ích của nó, nhưng khi cần thiết cho vấn đề hiệu suất.
Will Marcouiller

12
+1 cuối cùng đã nói với tôi rằng các tấm sprite thực sự có lý do tồn tại ngoài lý do thuận tiện cho lập trình viên / nhà thiết kế
Bill

3
+1 cho lời giải thích tuyệt vời, tôi đã học được rất nhiều từ câu trả lời của bạn.
Jesse Emond

1
Liên kết đến pdf "Batch, Batch, Batch" bị hỏng. Đây là một bản cập nhật: ce.u-sys.org/Veranstaltungen/ trộm
Marton

13

Theo một bài đăng trên các diễn đàn tại MSDN, khung XNA không làm hỏng việc:

Khung XNA sẽ không làm bất kỳ sự chán nản nào đối với bạn - nó không thể vì nó không có đầu mối nơi mọi thứ sẽ thực sự kết thúc. Tất cả các biến đổi được thực hiện trên GPU và có thể là một shader tùy chỉnh.

http://xboxforums.create.msdn.com/forums/p/22763/121897.aspx

Bài đăng này tiếp tục nói rằng, nếu bạn có nhiều đối tượng trong cảnh của mình, nó có thể đáng để bạn tự lăn.


6
Đặc biệt nếu bạn có một bản đồ cuộn (bạn nói đó là 2D, vì vậy điều này có thể có liên quan). Sẽ thật lãng phí nếu bạn vẽ những phần lớn không cần thiết. Nó không quá khó khăn và bạn có thể thấy một số cải tiến.
Michael Coleman

1

Tôi đã phát triển các công cụ địa hình voxel theo thủ tục trong vài năm nay tại XNA. Trong hầu hết các khung hình, các động cơ đang biến đổi theo nghĩa đen hàng trăm ngàn quads. Trong hồ sơ của tôi, tôi đã thấy rằng việc loại bỏ sự thất vọng và tắc nghẽn làm tăng hiệu suất.

Cấu hình HiDef của XNA (không phải Reach) có lớp OcinatingQuery được sử dụng để thực hiện Ocinating Culling. Ocinating Culling loại bỏ các quads đó khỏi một khung nhìn bị ẩn khỏi view bởi các quads khác.

Một cái gì đó khác mà bạn nên xem xét là thúc đẩy cả việc tạo và vận chuyển một cách riêng biệt.

Vì vậy, có, khi bạn tiếp cận một số lượng lớn các quads trong mỗi khung hình đang được chuyển đổi, bạn cần suy nghĩ cẩn thận về cách bạn có thể áp dụng các kỹ thuật loại bỏ và xâu chuỗi để duy trì tốc độ khung hình, bằng cách giảm lưu lượng truy cập cho các shader shpu.

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.