Tìm hiểu VAO và VBO
Tôi đang đọc qua Tìm hiểu OpenGL để làm mới các khái niệm cơ bản mà tôi đã không liên quan đến khá lâu.
Cụ thể là tôi vẫn nghĩ rằng tôi không thể hiểu rõ ý nghĩa của VAO và VBO, cuốn sách chủ yếu xem xét các ví dụ, nó không thực sự đưa ra các định nghĩa chặt chẽ.
Giới thiệu về VBO:
Với dữ liệu đỉnh được xác định, chúng tôi muốn gửi nó làm đầu vào cho quy trình đầu tiên của đường ống đồ họa: trình đổ bóng đỉnh. Điều này được thực hiện bằng cách tạo bộ nhớ trên GPU nơi chúng tôi lưu trữ dữ liệu đỉnh, định cấu hình cách OpenGL diễn giải bộ nhớ và chỉ định cách gửi dữ liệu đến cạc đồ họa. Sau đó, trình đổ bóng đỉnh xử lý càng nhiều đỉnh mà chúng ta yêu cầu từ bộ nhớ của nó. Chúng tôi quản lý bộ nhớ này thông qua cái gọi là các đối tượng đệm đỉnh (VBO) có thể lưu trữ một số lượng lớn các đỉnh trong bộ nhớ của GPU. Lợi thế của việc sử dụng các đối tượng đệm đó là chúng ta có thể gửi một loạt dữ liệu lớn cùng một lúc đến cạc đồ họa và giữ nó ở đó nếu còn đủ bộ nhớ mà không cần phải gửi dữ liệu từng đỉnh một. Việc gửi dữ liệu đến card đồ họa từ CPU tương đối chậm, vì vậy chúng tôi cố gắng gửi nhiều dữ liệu nhất có thể cùng một lúc ở bất cứ đâu. Khi dữ liệu nằm trong bộ nhớ của cạc đồ họa, trình đổ bóng đỉnh có thể truy cập gần như tức thì vào các đỉnh làm cho nó cực kỳ nhanh
Vì vậy, hiểu biết của tôi về VBO về cơ bản chúng là các đối tượng Buffer (một loạt các byte được gửi đến GPU) với sự khác biệt là VBO dành riêng cho Dữ liệu Vertex. Điều này có chính xác?
Về VAO:
Ở đây thay vào đó tôi không thực sự hiểu.
Một đối tượng mảng đỉnh (còn được gọi là VAO ) có thể được ràng buộc giống như một đối tượng bộ đệm đỉnh và bất kỳ lệnh gọi thuộc tính đỉnh nào tiếp theo từ điểm đó trở đi sẽ được lưu trữ bên trong VAO.
Điều đó có nghĩa là bất kỳ lệnh gọi thuộc tính đỉnh nào tiếp theo từ thời điểm đó trở đi sẽ được lưu trữ bên trong VAO , tôi không hiểu bit "lệnh gọi được lưu trữ", nó có nghĩa là ở đâu đó trong ngữ cảnh opengl được tạo ra, chúng tôi lưu trữ giống như một số dữ liệu liên quan đến các cuộc gọi thuộc tính đỉnh (như đầu ra cặp đầu vào của cuộc gọi? đầu ra của cuộc gọi? cái gì đó liên quan đến cuộc gọi?).
Điều này có lợi thế là khi cấu hình con trỏ thuộc tính đỉnh, bạn chỉ phải thực hiện các lệnh gọi đó một lần và bất cứ khi nào chúng ta muốn vẽ đối tượng, chúng ta có thể ràng buộc VAO tương ứng. Điều này làm cho việc chuyển đổi giữa các dữ liệu đỉnh khác nhau và các cấu hình thuộc tính dễ dàng như ràng buộc một VAO khác. Tất cả trạng thái chúng ta vừa thiết lập được lưu trữ bên trong VAO.
Tôi không hiểu lợi thế ở đây. Tôi hiểu "cuộc gọi được thực hiện một lần", bởi vì chúng được lưu trữ trong VAO (bất kể "phần được lưu trữ có nghĩa là gì"). Phần chuyển đổi có thể có nghĩa là tôi có thể tạo nhiều VAO, mỗi VAO nắm bắt các lệnh gọi Thuộc tính đỉnh khác nhau và tôi chỉ có thể ràng buộc từng thuộc tính này khi tôi cần mà không cần gọi lại thuộc tính đỉnh?
Để tham khảo, tôi cũng đã tìm thấy câu hỏi này mà tôi nghĩ có một câu trả lời thú vị.
Trả lời
Vì vậy, hiểu biết của tôi về VBO về cơ bản chúng là các đối tượng Buffer (một loạt các byte được gửi đến GPU) với sự khác biệt là VBO dành riêng cho Dữ liệu Vertex. Điều này có chính xác?
"VBO" không thực sự là một thứ gì đó, và tôi thực sự mong muốn các hướng dẫn sẽ ngừng giả vờ như vậy.
Bạn đúng ở chỗ tồn tại các đối tượng đệm . Đây là các mảng tuyến tính của dữ liệu chưa được định dạng mà GPU lưu trữ và có thể truy cập cho các quy trình khác nhau. Một trong những "quy trình khác nhau" mà GPU có thể sử dụng chúng là cung cấp dữ liệu mảng cho các hoạt động kết xuất đỉnh.
Nhưng bản thân bộ đệm không đặc biệt. Nó không trở thành một thứ khác chỉ vì bạn sử dụng nó cho dữ liệu đỉnh và không có quy tắc nào nói rằng bộ đệm bạn hiện đang sử dụng cho dữ liệu đỉnh cũng không thể được sử dụng cho các mục đích sử dụng bộ đệm khác.
Lưu ý rằng điều này khác với cách hoạt động của kết cấu. Khi bạn tạo một đối tượng kết cấu và liên kết nó dưới dạng kết cấu 2D, đối tượng kết cấu đó mãi mãi trở thành một kết cấu 2D. Sau đó, bạn không thể liên kết nó dưới dạng 1D hoặc cubemap hoặc bất cứ thứ gì. Các đối tượng đệm không phải như vậy; nơi bạn ràng buộc chúng chỉ xác định cách bạn hiện đang sử dụng chúng.
Nó có nghĩa là gì "bất kỳ lệnh gọi thuộc tính đỉnh tiếp theo nào từ thời điểm đó trở đi sẽ được lưu trữ bên trong VAO"
Đây là một trope hướng dẫn khó chịu khác: các đối tượng "lưu trữ cuộc gọi" hoặc là macro hoặc những thứ vô nghĩa khác.
Các đối tượng trong OpenGL không lưu trữ các cuộc gọi; họ lưu trữ trạng thái . Chúng giống như cấu trúc; họ có các thành viên dữ liệu. Việc ràng buộc một đối tượng với ngữ cảnh OpenGL cho phép các hoạt động OpenGL truy cập trạng thái nhất định để tìm trạng thái đó trong đối tượng bị ràng buộc. Vì vậy, nếu bạn gọi một hàm sửa đổi trạng thái nhất định từ một đối tượng bị ràng buộc, thì hàm đó sẽ sửa đổi trạng thái bên trong đối tượng.
Khi bạn ràng buộc một VAO, bạn đang ràng buộc một đối tượng lưu trữ trạng thái được sử dụng cho mảng đỉnh. Khi bạn gọi một hàm sửa đổi trạng thái cho mảng đỉnh, hàm đó sẽ sửa đổi trạng thái được lưu trữ trong VAO hiện bị ràng buộc. Khi bạn kết xuất, hệ thống kết xuất sẽ sử dụng trạng thái mảng đỉnh được tìm thấy trong VAO hiện đang bị ràng buộc.
VBO là một bộ đệm của bộ nhớ mà gpu có thể truy cập. Chỉ có vậy thôi.
VAO là một đối tượng lưu trữ các ràng buộc đỉnh. Điều này có nghĩa là khi bạn gọi glVertexAttribPointer và bạn bè để mô tả định dạng đỉnh của bạn, thông tin định dạng đó sẽ được lưu trữ vào VAO hiện được ràng buộc. Và khi bạn vẽ nó sẽ sử dụng các ràng buộc đỉnh trong VAO hiện đang bị ràng buộc.
Giả vờ nó phát lại các cuộc gọi ràng buộc là sai lầm. Đó là dấu tích lý do tại sao VAO được tạo ra bởi vì trước khi có VAO, bạn cần phải thực hiện lại các ràng buộc đỉnh mỗi khi bạn thay đổi lưới mà bạn đang vẽ. VAO cho phép bạn thực hiện điều đó trong một cuộc gọi.