Sự khác biệt trong glDrawArrays và glDrawElements


12

Trong khi làm mới tâm trí của tôi về OpenGL ES, tôi đã bắt gặp glDrawArraysglDrawElements.

Tôi hiểu làm thế nào chúng được sử dụng và sắp xếp hiểu tại sao chúng khác nhau.

Điều mà tôi dường như không hiểu là, tôi không thấy làm thế nào glDrawElementscó thể lưu các cuộc gọi rút thăm ( lưu các cuộc gọi rút thăm là một mô tả được đề cập bởi hầu hết các cuốn sách tôi đã đọc, do đó tôi đã đề cập đến nó ở đây).

Hãy tưởng tượng một kịch bản đơn giản trong đó tôi đã cố gắng vẽ một hình vuông bằng cách sử dụng 2 hình tam giác.

Tôi sẽ cần phải có một bộ 6 đỉnh sử dụng glDrawArraystrong khi sử dụng glDrawElements, tôi sẽ chỉ cần 4 đỉnh ngoài một mảng chỉ mục có 6 phần tử.

Với những điều trên, đây là những gì tôi không hiểu:

  1. Làm thế nào có thể glDrawElementslưu các cuộc gọi vẽ, nếu nó vẫn cần sử dụng mảng chỉ mục (6 chỉ số, trong trường hợp hình vuông) để lập chỉ mục vào mảng đỉnh của tôi có 4 phần tử (6 lần)? Nói cách khác, điều đó có nghĩa là glDrawElementsvẫn cần phải có tổng cộng 6 cuộc gọi rút thăm như thế glDrawArraysnào?
  2. Làm thế nào để sử dụng glDrawElementstiết kiệm không gian, nếu một vẫn cần có 2 mảng, một cho các đỉnh và một cho các chỉ số?
  3. Trong trường hợp vẽ một hình vuông từ 2 hình tam giác, để đơn giản, có bao nhiêu cuộc gọi vẽ glDrawElements(4 mục trong mảng đỉnh và 6 mục trong mảng chỉ mục) và glDrawArrays(6 mục chỉ trong mảng đỉnh) cần riêng lẻ?

Cảm ơn.

Câu trả lời:


15

Mỗi glDraw * là một cuộc gọi bốc thăm.

1 glDrawArrays là 1 cuộc gọi rút thăm.
1 glDrawElements là 1 cuộc gọi rút thăm.

Không thành vấn đề (liên quan đến số lần gọi rút thăm) có bao nhiêu đỉnh hoặc chỉ số bạn sử dụng, 1 glDraw * là 1 cuộc gọi rút thăm.

Các trường hợp đơn giản về vẽ các hình tứ giác (giả sử phiên bản GL bạn sử dụng chưa loại bỏ các hình tứ giác) hoặc hình tam giác không phải là một ví dụ tốt để so sánh các hình này, bởi vì một danh sách các hình tam giác hoặc danh sách các hình tam giác có thể được vẽ bằng một cuộc gọi duy nhất, và glDrawArrays sẽ xuất hiện hiệu quả hơn vì nó không có thêm chi phí lập chỉ mục.

Chúng ta hãy xem xét một trường hợp phức tạp hơn một chút, nhưng một trường hợp đại diện cho một kịch bản thực tế hơn. Hãy tưởng tượng rằng bạn có một mô hình bao gồm nhiều dải tam giác và quạt:

glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);

Trong ví dụ này, sử dụng glDrawArrays cung cấp cho bạn tổng cộng 6 lệnh gọi rút thăm cho mô hình. Tuy nhiên, cả dải và quạt có thể dễ dàng được chuyển đổi thành các hình tam giác được lập chỉ mục, vì vậy hãy thêm các chỉ số và nó trở thành:

glDrawElements (GL_TRIANGLES, .....);

Đó là một cuộc gọi rút thăm, cho toàn bộ mô hình.


Ưu điểm của glDrawElements so với glDrawArrays không chỉ là tiết kiệm bộ nhớ, đó là cách đo lường ngây thơ. Có khả năng tiết kiệm bộ nhớ trong đó các đỉnh có thể được sử dụng lại, bởi vì một chỉ mục thường nhỏ hơn một đỉnh (vì vậy ngay cả khi bạn có nhiều chỉ số trên số dư, chúng sẽ nhỏ hơn), nhưng các ưu điểm khác bao gồm:

  • Giảm số lượng cuộc gọi rút thăm. Mỗi lệnh gọi phát sinh một số chi phí từ trạng thái xác nhận, thiết lập mọi thứ, v.v. và phần lớn chi phí này xảy ra ở phía CPU. Bằng cách giảm số lượng cuộc gọi rút thăm, chúng tôi tránh được phần lớn chi phí này.

  • Vertex tái sử dụng. Điều này không chỉ là tiết kiệm bộ nhớ. GPU của bạn có thể có bộ đệm đỉnh phần cứng, nơi các đỉnh được chuyển đổi gần đây có thể được lưu trữ; nếu cùng một đỉnh xuất hiện trở lại và nếu trong bộ đệm, nó có thể được sử dụng lại từ bộ đệm thay vì phải chuyển đổi lại. Phần cứng của bạn sẽ kiểm tra bộ đệm bằng cách so sánh các chỉ số, vì vậy theo thuật ngữ OpenGL, cách duy nhất bạn có thể sử dụng bộ đệm là sử dụng glDrawElements.


Vì vậy, để trả lời các câu hỏi cụ thể của bạn:

  1. Làm thế nào glDrawElements có thể lưu các cuộc gọi rút thăm ...? Trong ví dụ bạn sử dụng, nó không. Mỗi người có một cuộc gọi rút thăm. Như tôi đã thảo luận ở trên, ví dụ này là một ví dụ rất tệ khi so sánh cả hai.

  2. Làm thế nào để sử dụng glDrawElements tiết kiệm không gian ...? Vì các chỉ số nhỏ hơn các đỉnh. Chỉ mục 16 bit là hai byte, đỉnh vị trí / màu / texcoord là 24 byte. 6 đỉnh là 144 byte, 4 đỉnh cộng với 6 chỉ số là 108 byte.

  3. Trong trường hợp vẽ hình vuông từ 2 hình tam giác ...? Một và một. Cuộc gọi glDraw * là một cuộc gọi rút thăm, số lượng đỉnh hoặc chỉ số được sử dụng là không liên quan đến phép đo này. Nhưng tôi phải nhấn mạnh lại, đây là một ví dụ rất tệ để so sánh hai.


Cuối cùng, và chỉ làm phức tạp vấn đề một chút, trong khi glDrawElements với hình tam giác là đường dẫn tối ưu trên GPU máy tính để bàn, trên thiết bị di động có thể rất khác. Một số GPU di động có thể thích glDrawArrays với GL_TRIANGLE_STRIP (bạn sẽ thêm các hình tam giác suy biến để ghép các nguyên thủy trong trường hợp này) và tôi thậm chí chưa chạm vào các chủ đề nâng cao hơn như khởi động lại nguyên thủy hoặc đa vẽ.


Cảm ơn rất nhiều cho phản hồi của bạn; Tôi chỉ dành một ít thời gian để đọc những gì bạn đã chia sẻ. Chỉ muốn cho bạn biết tôi thừa nhận phản hồi của bạn. Cảm ơn một lần nữa.
Unheilig

Trong ví dụ của bạn về việc chuyển đổi 6 cuộc gọi DrawTriginFans và DrawTriginStrips thành 1 cuộc gọi DrawTriangles duy nhất. Điều này thực sự cải thiện một số hiệu suất? Theo hiểu biết của tôi, vẽ một dải tam giác gồm 100 hình tam giác hiệu quả hơn nhiều so với vẽ 100 hình tam giác riêng lẻ và lợi ích sẽ dễ dàng bù đắp bất kỳ hình phạt nào xảy ra khi sử dụng 6 lệnh gọi thay vì 1.
Samuel Li

@SamuelLi 6-to-1 sẽ không phải là một cải tiến lớn, nó chỉ nhằm mục đích minh họa cho nguyên tắc này. Ngoài ra, và như tôi đã chỉ ra, các dải thường không phải là một chiến thắng hiệu suất trên các danh sách được lập chỉ mục trên phần cứng máy tính để bàn sau năm 1998. Kiểm tra ngày trên bất kỳ tài liệu nào khuyên bạn sử dụng dải.
Maximus Minimus

Có quan điểm của bạn, cảm ơn đã làm rõ! @MaximusMinimus
Samuel Li
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.