Cách hiệu quả nhất để vẽ đỉnh với OpenGL


8

Tôi đang viết một trò chơi OpenGL 3D. Sẽ có hàng tấn hình tam giác cho địa hình và vật thể đang sử dụng.

Tôi đang nghiên cứu từ hướng dẫn chính thức của OpenGL và phương pháp được trình bày đầu tiên là gọi một hàm glVertexsau glBeginmỗi đỉnh bạn muốn vẽ.

Tuy nhiên phương pháp này nghe có vẻ khá cổ xưa và không hiệu quả khi bạn phải vẽ hàng ngàn hình tam giác. Tôi đoán có những phương pháp để lưu trữ trong bộ nhớ card đồ họa, thông tin không thay đổi ở mọi khung hình để khi bạn kết xuất từng khung thì thông tin đó đã có sẵn. Mặc dù để có nhiều thông tin "không ổn định" hơn, có lẽ bạn phải gửi dữ liệu đỉnh mới mỗi khung và do đó, một tecnique khác có thể hiệu quả hơn.

Đến với câu hỏi của tôi: Tôi muốn một lời giải thích rõ ràng về các chức năng và kỹ thuật OpenGL hiện đại và hiệu quả nhất được sử dụng để gửi thông tin đỉnh đến phần cứng và đưa ra hướng dẫn để kết xuất.

Các cách tốt nhất và các công cụ OpenGL để gửi thứ tự hiển thị dữ liệu đỉnh ít khi thay đổi trong khung (tôi nghĩ về địa hình và đối tượng) và cách tốt nhất để gửi dữ liệu đỉnh thay đổi nhiều trong các khung là gì?


Bạn đã đúng, glBegin () và glEnd () là một phần của kết xuất chế độ ngay lập tức và khá lỗi thời. Ngày nay người ta sẽ sử dụng ví dụ VBO. Làm thế nào chính xác và những gì bạn sử dụng phụ thuộc vào kịch bản của bạn mặc dù!
thalador

Tôi cũng là một sinh viên cố gắng học OpenGL. Tôi biết rằng bạn sẽ cần sử dụng Đối tượng đệm của Vertex (VBO) để vẽ các đỉnh nhanh hơn. Mặc dù tôi không biết đủ để nói với bạn cách làm nhưng tôi có thể cung cấp cho bạn một liên kết đến một cuốn sách tuyệt vời (miễn phí trực tuyến). Tôi đã lướt qua nó và tạo ra một hình tam giác nhỏ nhưng nó thực sự phức tạp. Arcsynt tổng hợp Hướng dẫn OpenGL hiện đại Tôi đang xem qua hướng dẫn của LazyFoo ngay bây giờ. Chúng bắt đầu với đường ống chức năng cố định glBegin (), glEnd () sau đó chuyển sang OpenGL hiện đại hơn bằng cách sử dụng đường ống chức năng cố định làm nền tảng. Tôi sẽ j
benbot

Câu trả lời:


19

Nhìn rộng ra, câu trả lời là "nó phụ thuộc." Cách người ta gửi các bản cập nhật hạt khác một chút so với cách bạn gửi một loạt các mô hình có vỏ GPU.

Bộ đệm Vertex / Index

Tuy nhiên, theo nghĩa chung, mọi thứ ngày nay đều được thực hiện với VBO ( đối tượng bộ đệm đỉnh ). API chế độ tức thời ( glBegin/ glEnd) cũ có lẽ chỉ được triển khai như một trình bao bọc chất béo xung quanh hệ thống bộ đệm đỉnh bên trong của trình điều khiển.

Đối với các đối tượng tĩnh, tạo VBO tĩnh và điền dữ liệu đỉnh của bạn. Nếu bất kỳ đỉnh nào được chia sẻ (thường là trường hợp), có lẽ bạn cũng muốn tạo bộ đệm chỉ mục. Điều đó vừa giảm nhu cầu gửi cùng một dữ liệu nhiều lần để thay đổi các mắt lưới (có khả năng tiết kiệm băng thông truyền) và xử lý (tiết kiệm thời gian tạo bóng đỉnh). Lưu ý rằng bạn vẽ với các chức năng khác nhau khi thực hiện các lần rút chỉ mục so với các lần rút không được lập chỉ mục.

Đối với các đối tượng động, làm tương tự, mặc dù với một bộ đệm động.

Ghi chú nâng cao

Đối với các mảnh lớn hơn như địa hình, có lẽ bạn sẽ không chia lưới thành nhiều mảnh. Làm cho GPU hiển thị một trăm triệu hình tam giác khi chỉ nhìn thấy hai trăm nghìn trong số đó là một sự lãng phí rất lớn, đặc biệt là nếu chúng chưa được sắp xếp và có rất nhiều lời mời đổ bóng bị lãng phí. Chia lưới thành nhiều phần lớn và sau đó chỉ hiển thị những phần nằm trong chế độ xem. Ngoài ra còn có nhiều kỹ thuật loại bỏ tiên tiến hơn mà bạn có thể sử dụng để loại bỏ các khối có thể trong sự bực bội nhưng hoàn toàn ở phía sau một ngọn đồi hoặc tòa nhà hoặc một cái gì đó. Giữ số đếm cuộc gọi rút thăm là tốt, nhưng vẫn có sự cân bằng (mà bạn phải tìm cho ứng dụng / phần cứng cụ thể của mình) giữa việc giảm thiểu các cuộc gọi rút thăm và giảm thiểu việc vẽ hình học ẩn.

Một trong những điều quan trọng cần lưu ý với bộ đệm GPU là bạn không thể ghi vào nó trong khi GPU đang đọc từ nó. Bạn cần phải cho trình điều khiển biết rằng bạn có thể loại bỏ bản sao cũ của bộ đệm (khi hoàn thành) và đưa cho bạn một bản mới (nếu bản cũ đang bận). Tất nhiên trong một thời gian dài không có chức năng nào là OpenGL để làm điều này (bây giờ có UnlimitedateBufferData cho GL 4.3 và một số triển khai cũ hơn như một phần mở rộng). Thay vào đó, có một hành vi không chuẩn nhưng phổ biến mà hầu hết các trình điều khiển thực hiện. Làm điều này để loại bỏ bộ đệm trước khi cập nhật nó:

glBindBuffer(GL_ARRAY_BUFFER, my_vbo);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);

Tất nhiên thay đổi GL_ARRAY_BUFFERGL_DYNAMIC_DRAWcác giá trị thích hợp cho bộ đệm. Bộ đệm tĩnh sẽ không được cập nhật (hoặc không nên) vì vậy bạn không cần phải lo lắng về việc loại bỏ bộ đệm như vậy.

Lưu ý rằng nó có thể nhanh hơn để sử dụng glBufferDatahoặc glBufferSubDatacó thể nhanh hơn với glMapBuffer. Nó thực sự phụ thuộc vào trình điều khiển và phần cứng. Phần cứng PC thế hệ hiện tại có thể sẽ nhanh nhất glBufferDatanhưng kiểm tra để chắc chắn.

Một kỹ thuật khác là sử dụng inst instaging . Instaging cho phép bạn thực hiện một cuộc gọi rút thăm duy nhất rút ra nhiều bản sao của dữ liệu trong bộ đệm đỉnh / chỉ mục. Nếu bạn có 100 viên đá giống hệt nhau thì bạn sẽ muốn vẽ tất cả chúng trong một lần thay vì thực hiện 100 lần rút độc lập.

Khi kích hoạt, bạn cần đặt dữ liệu theo từng trường hợp vào một bộ đệm khác (như vị trí đối tượng của từng cá nhân). Đây có thể là một bộ đệm thống nhất ( bộ đệm không đổi theo thuật ngữ D3D) hoặc bộ đệm kết cấu hoặc thuộc tính đỉnh của mỗi thể hiện. Một lần nữa, đó là nhanh hơn phụ thuộc. Các thuộc tính theo trường hợp có thể nhanh hơn và chắc chắn dễ sử dụng hơn, nhưng nhiều triển khai GL phổ biến vẫn không hỗ trợ, glBindingAttribDivisorvì vậy bạn sẽ phải xem liệu nó có sẵn để sử dụng hay không và nó có thực sự nhanh hơn không (một số trình điều khiển cũ được mô phỏng bằng cách nối thêm bộ đệm và cuối cùng sử dụng việc kích hoạt chúng chậm hơn so với thực hiện các cuộc gọi rút thăm độc lập và không có cách nào chuẩn để tìm ra ... niềm vui của việc sử dụng OpenGL).

Ngoài ra còn có các thuật toán để tối ưu hóa bộ đệm đỉnh , đó là hành động sắp xếp các đỉnh / chỉ số trong bộ đệm của bạn để chơi với bộ đệm của đỉnh trên các GPU hiện đại. GPU sẽ chỉ chạy shader cho một đỉnh sau đó lưu nó vào bộ đệm của đỉnh nhưng nó có thể phải bị đuổi quá sớm để nhường chỗ cho các đỉnh khác. (Giả sử, hai hình tam giác đều có chung một đỉnh nhưng có 100 hình tam giác khác được vẽ giữa chúng; đỉnh được chia sẻ có thể sẽ bị đánh giá một cách lãng phí bởi bộ đổ bóng đỉnh hai lần.)

Một số tính năng này yêu cầu phiên bản GL hoặc GLES đủ mới. GLES2 đã không hỗ trợ inst instance, ví dụ.

Luôn hồ sơ

Một lần nữa, nếu bạn quan tâm đến hiệu suất, hãy kiểm tra từng phương pháp có thể và xem ứng dụng nào nhanh hơn cho ứng dụng của bạn trên phần cứng mục tiêu. Không chỉ các phần cứng / trình điều khiển khác nhau từ các nhà sản xuất khác nhau sẽ khác nhau mà một số lớp phần cứng hoàn toàn khác nhau. GPU di động điển hình là một con quái vật rất khác với GPU máy tính để bàn rời rạc điển hình. Kỹ thuật "tốt nhất" trên cái này không nhất thiết phải tốt nhất trên cái khác.

Khi nói đến hiệu suất, luôn luôn là một người hoài nghi .

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.