2015-06-14 10 views
5

Tôi đã xây dựng một công cụ đồ họa 2D và tôi đã tạo một hệ thống trộn cho nó, vì vậy, nếu tôi có 1000 sprites với cùng một kết cấu, tôi có thể vẽ chúng bằng một cuộc gọi duy nhất openGl.Hiển thị nhiều mô hình trong OpenGL với một lệnh gọi đơn

Điều này đạt được bằng cách đặt trong một vbo đỉnh mảng duy nhất tất cả các đỉnh của tất cả các sprites với cùng một kết cấu.

Thay vì "in các đỉnh này, in các đỉnh này, in các đỉnh", tôi làm "đặt tất cả các đỉnh lên, in", chỉ để rất rõ ràng. Dễ dàng, nhưng bây giờ tôi đang cố gắng để đạt được điều tương tự trong 3D, và tôi đang gặp một vấn đề lớn.

Vấn đề là tôi đang sử dụng ma trận Chiếu xem mô hình để đặt và hiển thị mô hình của tôi, đó là cách tiếp cận chung để hiển thị mô hình trong không gian 3D.

Đối với mỗi mô hình trên màn hình, tôi cần chuyển ma trận MVP vào trình đổ bóng, để tôi có thể sử dụng nó để biến đổi từng đỉnh thành vị trí chính xác.

Nếu tôi thực hiện phép chuyển đổi bên ngoài trình đổ bóng, nó sẽ được thực thi bởi CPU, mà tôi không phải là một ý tưởng hay, vì những lý do hiển nhiên.

Nhưng vấn đề nằm ở đó. Tôi cần truyền ma trận cho trình đổ bóng, nhưng đối với mỗi mô hình, ma trận là khác nhau.

Vì vậy, tôi không thể làm tương tự như tôi đã làm với 2ngày sprites, bởi vì thay đổi một đồng phục đổ bóng đòi hỏi phải vẽ mỗi lần.

Tôi hy vọng tôi đã rõ ràng, có thể bạn có một ý tưởng hay mà tôi không có hoặc bạn đã có cùng một vấn đề. Tôi biết thực tế là có giải pháp ở đâu đó, vì trong công cụ như Unity, bạn có thể sử dụng cùng một trình đổ bóng cho nhiều mô hình và nhận được một cuộc gọi vẽ

Trả lời

7

Có một tính năng chính xác như những gì bạn đang tìm kiếm và được gọi là instancing. Với instancing, bạn lưu trữ n ma trận (hoặc bất kỳ thứ gì khác bạn cần) trong Bộ đệm đồng bộ và gọi glDrawElementsInstanced để vẽ n bản sao. Trong trình đổ bóng, bạn nhận được một đầu vào bổ sung gl_InstanceID, mà bạn chỉ mục vào Bộ đệm đồng phục để tìm nạp ma trận bạn cần cho trường hợp cụ thể đó.

Bạn có thể đọc thêm về instancing đây: https://www.opengl.org/wiki/Vertex_Rendering#Instancing

+0

Câu trả lời thú vị! Tôi nghĩ về việc thực hiện một cái gì đó tương tự với bản thân mình, nhưng tôi đã không thực sự biết làm thế nào, đây chính xác là những gì tôi đang tìm kiếm – Ryno

1

Câu trả lời phụ thuộc vào việc các dữ liệu đỉnh cho mỗi mục là giống hệt nhau hay không. Nếu có, bạn có thể sử dụng tính năng instancing như trong câu trả lời của @ orost, sử dụng glDrawElementsInstancedgl_InstanceID trong trình đổ bóng đỉnh và phương thức đó nên được ưu tiên.

Tuy nhiên, nếu mỗi mô hình 3D yêu cầu dữ liệu đỉnh khác nhau (thường là trường hợp), bạn vẫn có thể hiển thị chúng bằng cách sử dụng một cuộc gọi vẽ duy nhất. Để làm điều này, bạn sẽ thêm một luồng khác vào dữ liệu đỉnh của mình với glVertexAttribPointer (và glEnableVertexAttribArray). Dòng bổ sung này sẽ chứa chỉ mục của ma trận trong bộ đệm đồng nhất mà đỉnh nên sử dụng khi kết xuất - vì vậy mỗi lưới trong VBO sẽ có chỉ mục giống nhau trong luồng bổ sung. Bộ đệm đồng bộ chứa cùng một dữ liệu như trong thiết lập instancing.

Lưu ý rằng phương pháp này có thể yêu cầu xử lý thêm CPU, nếu bạn cần làm lại đợt - ví dụ, một đối tượng trong một lô sẽ không được hiển thị nữa. Nếu quá trình này được yêu cầu thường xuyên, nó phải được xác định liệu các lô hàng thực sự có lợi hay không.

+0

Câu trả lời hay nhất cho đến giờ, nó thực sự giúp tôi hiểu cách tiếp cận nó ... Có lẽ tôi sẽ cố gắng viết một hệ thống tự động chọn instancing hoặc phương thức này ... Tôi có thể lưu cùng với các mắt lưới số đỉnh của nó. Sau đó, mỗi lần tôi thêm một lưới vào hệ thống, nếu số là giống nhau của lưới trước, tôi giữ một bool isInstance = true, nhưng ngay sau khi tôi nhận được một số khác nhau của đỉnh, tôi đặt nó thành false. Ở cuối khung hình tôi vẽ bằng một hoặc phương pháp khác, tùy thuộc vào giá trị bool – Ryno

+0

Có vẻ hợp lý với bạn? – Ryno

+0

@ user3578051 không chỉ số lượng đỉnh quan trọng mà còn là nội dung thực tế. Về cơ bản, bản chất chỉ vẽ cùng một lưới nhiều lần. Có lẽ bạn sẽ thay đổi dữ liệu thống nhất giữa các trường hợp. Trong phương thức này, nội dung của dữ liệu đệm đỉnh có thể hoàn toàn khác nhau giữa các cá thể. Một hệ thống có thể xử lý cả hai (và thích instancing) có lẽ sẽ là phương pháp đúng, ngoại trừ nếu nói rằng các lô của bạn thay đổi mọi khung hình. – MuertoExcobito

0

Bên cạnh instancing và thêm một thuộc tính đỉnh như một số đối tượng ID, tôi muốn cũng đề cập đến một chiến lược khác (mà đòi hỏi OpenGL hiện đại, mặc dù):

Việc gia hạn ARB_multi_draw_indirect (trong lõi từ GL 4.3) cho biết thêm gián tiếp lệnh vẽ. Các lệnh này làm nguồn tham số của chúng (số đỉnh, bắt đầu chỉ mục và vv) trực tiếp từ một đối tượng đệm khác. Với các chức năng này, nhiều đối tượng khác nhau có thể được vẽ bằng một cuộc gọi vẽ duy nhất.

Tuy nhiên, vì bạn vẫn muốn một số trạng thái cho mỗi đối tượng như ma trận chuyển đổi, tính năng đó là không đủ. Nhưng kết hợp với ARB_shader_draw_parameters (không phải trong lõi GL được nêu ra), bạn sẽ nhận được thông số , sẽ được tăng thêm một cho mỗi đối tượng trong một cuộc gọi gián tiếp rút nhiều. Bằng cách đó, bạn có thể lập chỉ mục vào một số UBO, hoặc TBO, hoặc SSBO (hoặc bất cứ điều gì), nơi bạn lưu trữ dữ liệu cho mỗi đối tượng.

Các vấn đề liên quan