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:
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.
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.
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ẽ.