Làm thế nào để cải thiện hiệu suất trộn


9

Tôi đang phát triển một trò chơi 2D dựa trên sprite cho (các) nền tảng di động và tôi đang sử dụng OpenGL (thật ra là Irrlicht) để kết xuất đồ họa. Đầu tiên tôi thực hiện kết xuất sprite theo cách đơn giản: mọi đối tượng trò chơi được kết xuất thành một hình tứ giác với lệnh gọi rút thăm GPU riêng, nghĩa là nếu tôi có 200 đối tượng trò chơi, tôi đã thực hiện 200 cuộc gọi rút thăm mỗi khung hình. Tất nhiên đây là một lựa chọn tồi và trò chơi của tôi hoàn toàn bị ràng buộc bởi CPU vì có một chút chi phí CPU được xác định trong mỗi cuộc gọi rút thăm GPU. GPU không hoạt động trong hầu hết thời gian.

Bây giờ, tôi nghĩ rằng tôi có thể cải thiện hiệu suất bằng cách thu thập các đối tượng thành các lô lớn và hiển thị các lô này chỉ bằng một vài cuộc gọi rút thăm. Tôi đã triển khai thực hiện theo đợt (để mọi đối tượng trò chơi có cùng kết cấu được hiển thị trong cùng một đợt) và nghĩ rằng các vấn đề của tôi đã biến mất ... chỉ để biết rằng tốc độ khung hình của tôi thậm chí còn thấp hơn trước.

Tại sao? Chà, tôi có 200 (hoặc nhiều hơn) các đối tượng trò chơi và chúng được cập nhật 60 lần mỗi giây. Mỗi khung hình tôi phải tính toán lại vị trí mới (dịch và xoay) cho các đỉnh trong CPU (GPU trên nền tảng di động không hỗ trợ kích hoạt nên tôi không thể thực hiện ở đó) và thực hiện phép tính này 48000 mỗi giây (200 * 60 * 4 kể từ khi mỗi sprite có 4 đỉnh) đơn giản là dường như quá chậm.

Tôi có thể làm gì để cải thiện hiệu suất? Tất cả các đối tượng trò chơi đang di chuyển / xoay (gần như) mọi khung hình vì vậy tôi thực sự phải tính toán lại các vị trí đỉnh. Chỉ tối ưu hóa mà tôi có thể nghĩ đến là một bảng tra cứu các phép quay để tôi không phải tính toán chúng. Điểm spites sẽ giúp đỡ? Bất kỳ hack khó chịu? Còn gì nữa không?

Cảm ơn.

Câu trả lời:


5

Bạn đã sử dụng cổng irrlicht của tôi cho Android? Đối với các sprite 2d trên Android và iphone, tôi sử dụng các thủ thuật tương tự như bạn: tạo khối. Tôi thử nhiều giải pháp trong OpenGL ES 1.x và 2.x:

  • sắp xếp theo z (parallax) và theo kết cấu, thực hiện các phép biến đổi trên CPU và gọi glDrawArrays hoặc glDrawElements (cách nhanh nhất). Sử dụng một kết cấu lớn nếu bạn có thể.
  • cùng một mẹo với VBO, không nhanh hơn vì với mỗi khung hình, bạn làm mới tất cả các thông tin. Nó có thể hữu ích cho các spites statics.
  • sử dụng OpenGL ES 2.x và sử dụng trình tạo bóng Vertex để tính toán các vị trí (chậm hơn)
  • sử dụng PointSprites (không có giải pháp nếu nó không phải là hình vuông và quá nhiều pixel trong suốt giết chết fillrate)
  • sử dụng tiện ích mở rộng gldrawtexoes ...
  • sử dụng một drawcall cho mỗi sprite (phương pháp chậm nhất)

Vì vậy, như bạn, tất cả các phép biến đổi được CPU thực hiện cho OGLES 1.x hoặc OGLES 2.x. Nếu bạn có hướng dẫn neon, bạn có thể sử dụng chúng để tăng tốc độ tính toán của mình.

Ps: trên thiết bị iphone hoặc android, tôi không giới hạn CPU nhưng giới hạn tốc độ lấp đầy. Vì vậy, nó là rất quan trọng để hạn chế rút tiền.


Tuyệt vời, đây là thứ tôi đang tìm kiếm. Tôi không biết về cổng Irrlicht của bạn nhưng tôi đã có phiên bản Irrlicht chạy trên iOS rồi. Bạn nói rằng bạn không bị giới hạn CPU - bạn đang vẽ bao nhiêu họa tiết? Và tốc độ khung hình của bạn là gì, nói, cho 100 sprite trên iPhone? Nếu tôi có 200 đối tượng, cuối cùng tôi sẽ thực hiện 48000 phép tính mỗi giây. Quan điểm của bạn về fillrate là tốt.
dùng4241

Sprite tĩnh (nền) là trong VBO. Tôi sử dụng một VBO cho mỗi thị sai. Nếu không, tôi có 100 đến 200 sprite trên Moblox. Trên tất cả các điện thoại thông minh bao gồm cả 3G, tôi có hơn 30 khung hình / giây (như tôi nhớ). Nhưng các họa tiết lớn rất tốn kém (vấn đề điền vào) ....
Ellis

Tôi đang làm việc trên một công cụ hạt, tôi có thể sử dụng tới 20 000 hạt với tất cả các vị trí tính toán được thực hiện trên CPU và tôi có 10 khung hình / giây với các cài đặt cực đoan (trên 3GS và iPhone4). Vì vậy, 1000 sprite phải có thể có trên 3GS hoặc iPhone4 với tốc độ khung hình tốt.
Ellis

Cảm ơn bạn, rất hữu ích! Làm thế nào bạn đang thực hiện động cơ hạt của bạn? Tôi cho rằng bạn đang chơi xung quanh với shader?
dùng4241

Tôi sử dụng shader vì tôi cần gl_PointSize để thiết lập từng kích thước hạt. Tôi không làm việc nữa với OGLES 1.x vì điện thoại cũ không phải là mục tiêu của tôi. Đầu tiên, tất cả mã của tôi là OGLES 1.x, sau đó là OGLES 1.x và OGLES 2.x (không cải thiện hiệu suất) và giờ là OGLES 2.x (cải thiện kết xuất).
Ellis

1

Tôi khuyên bạn nên có một VBO, với mỗi đỉnh chứa vị trí / góc quay của từng đối tượng được kết xuất và tạo khối dựa trên kết cấu như bạn đang làm. Tôi không quen thuộc với ES ogl, vì vậy tôi không chắc nó hỗ trợ phiên bản glsl nào, nhưng bạn thậm chí có thể bó theo dựa trên một tập hợp họa tiết và lưu trữ trong số 4 hoặc hơn kết cấu bạn đang đi qua trong bạn đang sử dụng bên trong đỉnh. Các sprite điểm chắc chắn sẽ cải thiện hiệu suất của bạn vì nó sẽ cắt giảm lượng dữ liệu bạn gửi đi một cách quyết liệt và việc bó không bao giờ làm giảm hiệu suất nếu bạn thực hiện đúng. Ngoài ra, bạn có thể cải thiện hiệu suất một chút bằng cách tính toán xoay trên trình đổ bóng và chỉ chuyển một giá trị int / float vào các thông số hoặc bên trong đỉnh. (params sẽ nhanh hơn,


Cảm ơn bạn vì câu trả lời. Gợi ý của bạn về việc thực hiện tính toán xoay trong shader là tuyệt vời nhưng thật không may, tôi đang sử dụng OpenGL ES 1 không hỗ trợ trình đổ bóng nên tôi bị kẹt với đường ống cố định. Tôi sẽ thử các họa tiết điểm nhưng tôi không thể sử dụng chúng trong mọi trường hợp vì có giới hạn trên cho kích thước của chúng. Tôi vẫn còn chút bi quan về VBO, nếu tôi tính toán lại vị trí của từng đỉnh mỗi khung hình, VBO sẽ giúp như thế nào?
dùng4241

nó cho phép dữ liệu đỉnh của bạn ở lại trên gpu, điều này làm giảm lượng dữ liệu bạn phải gửi qua gpu mỗi khung. bạn không cần các shader để tận dụng lợi thế của tho này, bạn không cần phải thay đổi dữ liệu đỉnh, nếu bạn có một vị trí cơ sở (chẳng hạn như gốc) cho mỗi sprite, bạn chỉ có thể thay đổi ma trận thế giới bằng cách nó biến đổi trước khi gọi bốc thăm. tuy nhiên, điều này có thể khó khăn khi trộn. sử dụng chức năng cố định, có lẽ sẽ có ích hơn khi chỉ cần chuyển sang VBO và bỏ đợt ít nhất bây giờ, điều đó chắc chắn sẽ giúp bạn tăng sức mạnh.
sringer

Tôi thấy điểm của bạn. Vì vậy, sau tất cả, bạn không nói về việc tạo khối mà chỉ sử dụng một lệnh gọi để vẽ một đối tượng trò chơi. Tôi chắc chắn sẽ kiểm tra VBO mà không theo đợt ảnh hưởng đến FPS trong trò chơi của tôi nhưng vẫn có 200 cuộc gọi rút thăm cho mỗi khung hình nghe có vẻ quá lớn ... nhưng tôi đoán rằng tôi phải sống với nó sau đó. Tôi sẽ chấp nhận câu trả lời của bạn nếu không có câu trả lời nào khác xuất hiện.
dùng4241

1

Bạn đề cập đến các nền tảng di động không có sự thay đổi. Nhưng, bạn vẫn có shader đỉnh, phải không?

Trong trường hợp đó, bạn vẫn có thể thực hiện giả mạo, điều này cũng rất nhanh. Tạo một VBO (GL_STATIC_DRAW) với các điểm góc (liên quan đến điểm trung tâm của sprite, ví dụ: -1 / -1, 1 / -1, 1/1, -1/1) và bất kỳ tọa độ kết cấu nào bạn cần, trong đó .
Sau đó, đặt một trong các thuộc tính đỉnh chung cho mỗi lệnh gọi vẽ tới điểm trung tâm của sprite và vẽ hai hình tam giác với bộ đệm bị ràng buộc. Bên trong shader đỉnh, đọc thuộc tính đỉnh chung và thêm tọa độ của đỉnh.

Điều đó sẽ giúp bạn tiết kiệm việc truyền dữ liệu cho mỗi sprite và sẽ nhanh hơn nhiều. Số lượng cuộc gọi rút thăm thực tế không quá quan trọng, việc chặn / tạm dừng ở giữa là.


Đây là giải pháp tốt cho OpenGL ES 2.0. Thật không may, tôi đang sử dụng ES 1 mà không có shader nào cả.
dùng4241

0

Vấn đề nằm ở lượng dữ liệu bạn đang gửi tới GPU mỗi khung. Chỉ cần tạo VBO cho mỗi lô và điền vào một lần, sau đó áp dụng ma trận biến đổi tương ứng (thông qua glMultMatrix hoặc shader nếu bạn đang sử dụng ES 2.0) khi vẽ các lô.


Tôi không hiểu điều này giúp ích gì khi tôi có 200 đối tượng trò chơi riêng biệt với các biến đổi độc đáo? Sử dụng glMultMatrix sẽ áp dụng cùng một phép biến đổi cho tất cả các đối tượng không phải là điều tôi muốn. Ngoài ra, gửi dữ liệu tới GPU không bị tắc nghẽn; Nếu tôi loại bỏ sự biến đổi phía CPU thì rất tốt.
dùng4241

Có, nhưng VBO vẫn có thể cải thiện hiệu suất nếu được áp dụng đúng cách. Hiện tại bạn đang kết xuất 200 đối tượng của mình như thế nào? Bạn đang sử dụng glBegin / glEnd?
TheBuzzSaw

1
Tôi đang sử dụng công cụ Irrlicht 3D với nút cảnh tùy chỉnh nên tôi không sử dụng OpenGL trực tiếp (nhưng tôi cho rằng nó sử dụng glBegin / glEnd đơn giản trong trường hợp này). VBO có thực sự giúp vì tôi sẽ phải sửa đổi toàn bộ bộ đệm mỗi khung không? Ngoài ra, điều này không giải quyết được vấn đề cơ bản về việc bị ràng buộc bởi CPU vì các tính toán biến đổi đỉnh. Nhưng dù sao cũng cảm ơn bạn vì câu trả lời của bạn!
dùng4241
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.