2013-04-12 28 views
5

Vì vậy, một yêu cầu quan trọng đối với lập trình OpenGL là bạn lưu trữ các đỉnh của bạn theo kiểu thời trang đảm bảo bộ nhớ tiếp giáp. Tôi đã đọc một vài cuốn sách phong nha gần đây bởi các lập trình viên đồ họa chuyên nghiệp, và cả hai đều sử dụng một biến thể của cùng một ý tưởng: đóng gói các đỉnh thành một struct của 3 floats, x, y, z và sau đó đóng gói nhiều đỉnh vào một c mảng kiểu hoặc std::vector trong số này structs. Và nó hoạt động.Bộ nhớ liền kề, OpenGL và cách bạn gói các đỉnh của mình?

Nhưng tôi đã nhìn thấy nó nói nhiều lần trên trang web này rằng struct không đảm bảo tiếp giáp bộ nhớ. Người ta nói rằng nếu cấu trúc của bạn chứa tất cả floats thì chúng sẽ có thể là là liền kề, nhưng nó không được đảm bảo.arraystd::vector đảm bảo điều đó, nhưng điều đó không liên quan nếu những gì bạn đang đưa vào mảng hoặc vectơ không tiếp giáp.

Đối với mã sản xuất, tôi hy vọng rằng "có thể là" không cắt. Vì vậy, bất chấp gợi ý trong hai cuốn sách này, rõ ràng là hướng đến việc học tập, tôi muốn biết một số kỹ thuật tốt khác để dễ dàng tổ chức dữ liệu đỉnh theo cách nào mà bảo đảm bộ nhớ tiếp giáp, hoặc, tôi chấp nhận những lời khuyên mà tôi không nên lo lắng về điều này, rằng có lẽ nên là đủ tốt.

Các phương pháp phổ biến và tốt khác được sử dụng trong trường đồ họa là gì?

+0

Ngoài bất kỳ biện pháp phòng ngừa nào khác bạn có thể thực hiện, hãy ném mã này vào mã của bạn: 'static_assert (sizeof (vertex) == sizeof (float) * 3," vertex not aligned aligned "); sửa đổi chuỗi công cụ của bạn, các giả định của bạn sẽ không thành công, bạn sẽ được thông báo khi biên dịch. –

+0

Nó có thể không được đảm bảo bởi tiêu chuẩn C++ nhưng nó có thể được chỉ định bởi "tiêu chuẩn" ABI trên một nền tảng cụ thể. Điều đó có nghĩa rằng một khi bạn đã thiết lập nó hoạt động trên một nền tảng nó sẽ không thay đổi không thể đoán trước hoặc nó sẽ phá vỡ tất cả các thư viện được biên dịch. Về cơ bản, tiêu chuẩn C++ không phải là tiêu chuẩn duy nhất áp dụng, mỗi nền tảng có một tiêu chuẩn cho những thứ này. Ngay cả khi nó không phải là một văn bản, tiêu chuẩn xuất bản của nó vẫn sẽ không dễ dàng bị phá vỡ. Tất nhiên bạn phải chắc chắn rằng khi chuyển sang một nền tảng, giả định của bạn là chính xác, nhưng sau đó tôi không thể nhìn thấy nó phá vỡ. – jcoder

Trả lời

5

Vì vậy, yêu cầu quan trọng đối với lập trình OpenGL là bạn lưu trữ các đỉnh theo cách đảm bảo bộ nhớ liền kề.

Không thực sự. Bộ nhớ liền kề tiết kiệm không gian, nhưng miễn là stride (khoảng cách tính bằng byte) giữa các thuộc tính là giống nhau giữa tất cả các phần tử, thì điều này sẽ hoạt động.

Phương pháp phổ biến và tốt khác được sử dụng trong trường đồ họa là gì?

đơn giản, đơn giản, các mảng phẳng của các kiểu dữ liệu nguyên thủy, như std::vector<float>, hoặc std::vector<char> nếu bạn chỉ muốn một hunk bộ nhớ trong mà bạn trải ra các dữ liệu bằng tay contigously. Bạn có thể bọc này là trong một lớp học độc đáo với các phương thức getter và setter và các giao diện trình lặp mà trừu tượng hóa các phép tính offset và stride.

Bạn cũng có thể sử dụng cấu trúc nếu bạn có thể sử dụng các phần mở rộng trình biên dịch để chỉ định bố cục bộ nhớ của nó. Ví dụ: __attribute__((packed)) của GCC sẽ tạo cấu trúc chặt chẽ của các phần tử không có khoảng trống giữa.

+0

Thú vị, cảm ơn. Bạn có muốn biết về bất kỳ ví dụ hay mẫu mã nào tốt có thể có lớp bao bọc như bạn đề cập không? – johnbakers

2

OpenGL Mathematics Library, glm, có sự đảm bảo rằng vectơ của nó là tiếp giáp và đơn giản trong bộ nhớ, mà cá nhân tôi sử dụng để lưu trữ các đỉnh trong:

std::vector<glm::vec3> positions; 
std::vector<glm::vec2> texCoords; 

Nó cũng có một tiện ích để đúc các địa chỉ của cấu trúc của nó một cách an toàn trong các hàm OpenGL glXXXv.

Nếu bạn muốn có mọi thứ trong một VBO, bạn sẽ phải tạo một số loại cấu trúc phức hợp, bởi vì tôi sợ rằng std::tuple<glm::vec3, glm::vec2>is not up for the challenge, điều này hơi buồn.


Như có vẻ như, the glm behaviour is not backed by the standard, mà có thể đã thay đổi với C++ 11 và alignas() mặc dù. Tuy nhiên, bạn khó có thể làm tốt hơn về việc sắp xếp các cấu trúc, tôi đoán, và đề xuất static_assert sẽ ngăn bạn tự bắn mình vào chân.