5

Tôi hiện đang sử dụng các lớp GLTools đi kèm với ấn bản Superbible 5th. Tôi đang tìm trong lớp GLTriangleBatch và nó có đoạn mã sau:Đối tượng đệm OpenGL Vertex, tôi có thể truy cập dữ liệu đỉnh cho các mục đích khác như phát hiện va chạm không?

// Create the master vertex array object 
glGenVertexArrays(1, &vertexArrayBufferObject); 
glBindVertexArray(vertexArrayBufferObject); 


// Create the buffer objects 
glGenBuffers(4, bufferObjects); 

#define VERTEX_DATA  0 
#define NORMAL_DATA  1 
#define TEXTURE_DATA 2 
#define INDEX_DATA  3 

// Copy data to video memory 
// Vertex data 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_VERTEX); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pVerts, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0); 

// Normal data 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[NORMAL_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_NORMAL); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*3, pNorms, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0); 

// Texture coordinates 
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[TEXTURE_DATA]); 
glEnableVertexAttribArray(GLT_ATTRIBUTE_TEXTURE0); 
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*nNumVerts*2, pTexCoords, GL_STATIC_DRAW); 
glVertexAttribPointer(GLT_ATTRIBUTE_TEXTURE0, 2, GL_FLOAT, GL_FALSE, 0, 0); 

// Indexes 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*nNumIndexes, pIndexes, GL_STATIC_DRAW); 

// Done 
glBindVertexArray(0); 

// Free older, larger arrays 
delete [] pIndexes; 
delete [] pVerts; 
delete [] pNorms; 
delete [] pTexCoords; 

// Reasign pointers so they are marked as unused 
pIndexes = NULL; 
pVerts = NULL; 
pNorms = NULL; 
pTexCoords = NULL; 

Từ những gì tôi hiểu mã vượt qua mảng mà các con trỏ pVerts, pNorms, pTexCoords, pIndexes và lưu trữ chúng trong một đối tượng mảng Vertex, về cơ bản là một mảng các đối tượng đệm đỉnh. Chúng được lưu trữ trong bộ nhớ trên GPU. Các con trỏ ban đầu sau đó sẽ bị xóa.

Tôi quan tâm đến việc truy cập các vị trí đỉnh, được giữ trong mảng pVert được trỏ tới.

Bây giờ câu hỏi của tôi xoay quanh phát hiện va chạm. Tôi muốn có thể truy cập vào một mảng của tất cả các đỉnh của GLTriangleBatch của tôi. Tôi có thể lấy chúng qua số vertexBufferObject sau này bằng cách sử dụng một số loại phương thức getter? Nó sẽ là tốt nhất để chỉ giữ con trỏ pVerts xung quanh và sử dụng một phương thức getter cho rằng thay vào đó? Tôi đang suy nghĩ về hiệu suất, vì tôi hy vọng sẽ triển khai thuật toán phát hiện va chạm GJK trong tương lai ...

Trả lời

7

Đối tượng đệm, khi được sử dụng làm nguồn cho dữ liệu đỉnh, tồn tại vì lợi ích của rendering. Đi ngược lại (đọc lại dữ liệu) thường không được khuyến khích từ quan điểm thực hiện.

Gợi ý bạn cung cấp cho glBufferData có ba mẫu truy cập: BẢN V,, ĐỌC và BẢN SAO; những điều này cho OpenGL biết bạn định lấy/lấy dữ liệu trực tiếp từ đối tượng bộ đệm như thế nào. Các gợi ý không chi phối cách OpenGL nên đọc/ghi từ/đến nó. Đây chỉ là gợi ý; API không thực thi bất kỳ hành vi cụ thể nào, nhưng vi phạm chúng có thể dẫn đến hiệu suất kém.

DRAW có nghĩa là bạn sẽ đưa dữ liệu vào bộ đệm, nhưng bạn sẽ không đọc từ bộ đệm đó. ĐỌC có nghĩa là bạn sẽ đọc dữ liệu từ bộ đệm, nhưng bạn sẽ không ghi vào nó (thường là để chuyển đổi phản hồi hoặc bộ đệm pixel). Và COPY có nghĩa là bạn sẽ không đọc hoặc ghi trực tiếp vào bộ đệm.

Lưu ý rằng không có gợi ý cho "đọc và viết". Chỉ có "viết", "đọc" và "không phải". Hãy xem xét rằng một gợi ý là làm thế nào tốt của một ý tưởng đó là để ghi dữ liệu vào một bộ đệm trực tiếp và sau đó bắt đầu đọc từ bộ đệm đó.

Một lần nữa, các gợi ý dành cho người dùng trực tiếp nhận hoặc truy xuất dữ liệu. glBufferData, glBufferSubData và tất cả các chức năng ánh xạ khác nhau đều ghi, trong khi glGetBufferSubData và chức năng ánh xạ tất cả đều đọc.

Trong mọi trường hợp không, bạn không nên làm điều này. Giữ một bản sao dữ liệu vị trí xung quanh trong bộ nhớ máy khách nếu bạn cần sử dụng nó trên máy khách.

Ngoài ra, một số trình điều khiển bỏ qua các gợi ý sử dụng hoàn toàn. Thay vào đó, họ quyết định nơi đặt đối tượng bộ đệm dựa trên cách bạn sử dụng nó, thay vì cách bạn nói bạn định sử dụng nó. Điều này sẽ tồi tệ hơn cho bạn, bởi vì nếu bạn bắt đầu đọc từ bộ đệm đó, trình điều khiển có thể di chuyển dữ liệu của bộ đệm vào bộ nhớ không nhanh. Nó có thể được di chuyển ra khỏi GPU và thậm chí vào không gian bộ nhớ máy khách.

Tuy nhiên, nếu bạn nhấn mạnh vào việc này, có hai cách để đọc dữ liệu từ đối tượng bộ đệm. glGetBufferSubData là nghịch đảo của glBufferSubData. Và bạn luôn có thể ánh xạ bộ đệm để đọc thay vì viết.

+1

Cảm ơn bạn! Câu trả lời đó rất hữu ích! Tôi sẽ giữ con trỏ pVert xung quanh để truy cập dữ liệu đỉnh sau này. – kbirk

+0

@ user785259: Chỉ giữ con trỏ không đủ. Bạn thực sự phải giữ bộ nhớ được cấp phát, tức là không phải 'xóa []' hoặc 'miễn phí (...)' nó. Ngay cả sau khi giải phóng bộ nhớ bạn vẫn có thể có con trỏ trong C, mà sau đó là không hợp lệ. Có lẽ bạn đang đến từ một ngôn ngữ thu gom rác thải, sau đó loại bỏ một con trỏ thực sự ngụ ý giải phóng bộ nhớ, và có, đây là ngữ nghĩa sane. Nhưng đây là C++ bạn đang đối phó với và tất cả việc này là một sự cần thiết không thể tránh khỏi ở đó. – datenwolf

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