2010-12-13 17 views
5

Mọi người liên tục bảo tôi sử dụng ít nhất Vertex Arrays. Nhưng tôi nghĩ rằng nó không phải là một ý tưởng tốt vì tôi đang sử dụng glPushMatrix() với glTranslatef/glRotatef để định vị một đối tượng trong thế giới 3D. Vì vậy, tôi có nên ngừng sử dụng glPushMatrix() và tính toán vị trí đỉnh xoay/di chuyển trên thế giới "theo cách thủ công" và sau đó đẩy dữ liệu đỉnh của chúng vào một mảng đỉnh và sau đó kết xuất tất cả cùng một lúc không? Không.OpenGL: Làm thế nào để thiết kế hệ thống dựng hình hiệu quả bằng cách sử dụng mảng đỉnh với phân loại chiều sâu?

Nhưng, tất cả điều này sẽ trở nên rối rắm hơn khi tôi sử dụng các bề mặt kết cấu khác nhau cho tất cả các đối tượng trên màn hình cũng được sắp xếp theo chiều sâu.

Vì vậy:

  1. tôi sẽ phải để lưu trữ từng đối tượng với ID bề mặt kết cấu là tốt.
  2. Tôi sẽ sắp xếp tất cả các đối tượng hiển thị theo vị trí Z của chúng (trò chơi chỉ được xem từ trên xuống và tất cả các đối tượng đều bằng phẳng).
  3. tôi sẽ đi qua mảng được sắp xếp này:
  4. Tạo bộ đệm mới và sao chép chỉ đỉnh/texcoord/màu/bình thường vào bộ đệm này:
  5. Mỗi lần ID bề mặt kết cấu đã thay đổi từ ID trước, tôi sẽ ràng buộc với ID kết cấu chính xác:
  6. Tải lên dữ liệu đỉnh tôi đã thu thập được.
  7. Giải phóng bộ đệm được sử dụng cho mảng đỉnh tạm thời.
  8. Lặp lại các bước 4-7 cho đến khi tôi đã trải qua tất cả dữ liệu tôi đã sắp xếp ở vị trí đầu tiên.
  9. Miễn phí dữ liệu mảng đã sắp xếp của tôi và lặp lại các bước 1-9.

Tôi có làm đúng không?

Ngoài ra, tôi nên thiết kế cấu trúc dữ liệu cho các đối tượng mà tôi sắp xếp như thế nào? Ví dụ: sử dụng std::vector để lưu trữ dữ liệu đỉnh cho từng đối tượng có tốt không? Hoặc là có lựa chọn tốt hơn? Tôi đã suy nghĩ rằng std::vector để lưu trữ tất cả các dữ liệu này sẽ như thế nào:

struct GameObject { 
    int TexID; 
    float z; // we will sort by this 
    vector<VTCNStruct> VertexData; // store each point of the object here (including color/normal/texcoord points). 
}; 

vector<GameObject> GameObjectBuffer; // push all sortable objects here 

Ngoài ra, ở bước 4: là nó có thể sử dụng std::vector đã tồn tại trong trường hợp này? Tôi đã có ý tưởng rằng tôi phải sử dụng mảng thô, chẳng hạn như new float[100] để gửi mảng đỉnh tới GPU của mình hoặc bằng cách nào đó tôi đã sử dụng sắp xếp std::vector ở đây bằng cách nào đó (hiệu quả) mà không tạo bộ đệm mới mỗi khi ID kết cấu thay đổi ?

Trả lời

2

Bạn nên giữ một mảng đỉnh cho mỗi đối tượng. Không sử dụng glTranslatef/glRotatef, v.v. Thay vào đó, thu gọn các biến đổi thành một ma trận. Sử dụng ma trận đó để phân loại chiều sâu đối tượng của bạn. Sau đó vẽ các đối tượng của bạn từ trước ra sau bằng cách đẩy ma trận biến đổi đối tượng, vẽ mảng đỉnh, sau đó popping ma trận biến đổi.

Cách tiếp cận này có nghĩa là bạn đang không ngừng tạo ra và giải phóng các mảng để lưu trữ các dữ liệu đỉnh trong.

Như việc sử dụng std :: vector, hầu hết các trường sử dụng một mảng C liệu bên trong, do đó, bạn có thể làm & myVec [0] để truy cập vào mảng đó. Tuy nhiên, đừng cố gắng duy trì con trỏ đó vì vector std :: có thể thay đổi realloc mảng của nó và sau đó con trỏ đã tồn tại của bạn sẽ không còn hợp lệ nữa.

+0

"Bạn nên giữ một mảng đỉnh mỗi đối tượng" - là thông minh này ở tất cả? vì hầu hết các đối tượng của tôi chỉ là quad, và không sử dụng băng thông nhiều hơn bây giờ khi tôi không gửi nhiều dữ liệu hơn tới GPU (có nghĩa là mảng màu/mảng bình thường), nhưng tôi cũng cần gửi các lệnh tải lên mảng đỉnh giữa mọi đối tượng . – Newbie

+0

Làm cách nào để tôi thu gọn các biến đổi của tôi thành một ma trận? Ngoài ra, bạn không có nghĩa là từ trở lại phía trước? Vì vậy, về cơ bản bạn đề nghị tôi sẽ giữ 'glPushMatrix()' nhưng thay vì 'glBegin/glEnd' tôi sẽ sử dụng mảng đỉnh? NẾU tôi muốn sử dụng VBO thay vào đó, tôi nên giữ cùng một cách tiếp cận bạn đề nghị? – Newbie

+0

Newbie-Tôi không phải là lập trình viên OpenGL, nhưng tôi tin Josh có nghĩa là bạn nên vẽ các đối tượng phía trước (ví dụ: tủ quần áo để màn hình) trước tiên, xa nhất cuối cùng. EDIT - Bằng cách sụp đổ biến đổi thành một ma trận, tôi tin rằng bạn có thể sử dụng một số thủ thuật toán học để có được một biến đổi cho cả hai di chuyển/xoay/etc. Đã rơi vào một cuộc đột kích. – ZachS

11

Xin từ bỏ glBegin/glEnd ngay bây giờ, nó không còn được dùng nữa và đã bị xóa khỏi OpenGL-4. Bạn chắc chắn nên sử dụng các mảng đỉnh, thậm chí tốt hơn nếu bạn sử dụng các đối tượng đệm đỉnh.

Sử dụng chế độ ngay lập tức (glBegin/glEnd) trình điều khiển OpenGL phải tạo một mảng đỉnh từ các cuộc gọi hàm. Vì không rõ có bao nhiêu đỉnh sẽ đến, nó cuối cùng sẽ cấp phát lại bộ nhớ nhiều lần (thời gian mà GPU trực tiếp thực thi các cuộc gọi giữa glBegin/glEnd dài hơn).

Sử dụng mảng đỉnh sẽ không bao giờ kém hiệu quả hơn chế độ ngay lập tức. Bạn có thể đặt hình học của nhiều đối tượng vào một mảng đỉnh, bạn có thể tách chúng ra khỏi danh sách chỉ mục đỉnh. Danh sách chỉ mục Vertex cũng có thể được lưu trữ trong các đối tượng đệm.

Sau đó, giữa việc vẽ các đối tượng sẽ điều chỉnh ma trận modelview.

trật tự phân loại nên như followig:

  1. chia thành các đối tượng đục và mờ. Sắp xếp opaque
  2. Sắp xếp các opqaues theo các đối tượng GL (kết cấu, đổ bóng, vật liệu, vv) vì việc chuyển đổi các đối tượng GL là đắt nhất.
  3. Đối với mỗi nhóm đối tượng GL biệt loại gần xa và vẽ theo thứ tự
  4. Sắp xếp translucents xa đến gần và vẽ theo thứ tự mà

Bạn không nên cố gắng quan trọng xung quanh với bộ đệm cập nhật mới/downloads. Chỉ cần tải lên dữ liệu đỉnh một lần và sau đó chỉ cần điều chỉnh các mảng chỉ mục và thứ tự mà chúng được gửi. Không cần phải lo lắng về bộ nhớ OpenGL có sẵn, không có giới hạn nào được thi hành. Nếu dữ liệu của bạn không phù hợp với GPU RAM, trình điều khiển có trách nhiệm trao đổi nó với bộ nhớ hệ thống - đó cũng là lý do tại sao bạn nên sắp xếp các đối tượng OpenGL trước, bởi vì mỗi khi bạn chuyển đổi các đối tượng OpenGL (glBindTexture, glBindBuffer, vv) cần trao đổi, vì vậy bạn muốn giữ cho các hoạt động hoán đổi đó ở mức tối thiểu. Số lượng dữ liệu gửi đến GPU dưới dạng mảng chỉ số sẽ được ít hơn nhiều, so với những gì được gửi theo phương thức trực tiếp gọi ở mức tối thiểu:

  • mảng Index: 16 bit cho mỗi đỉnh (16 chỉ số kích thước chút là nhất biểu diễn).

  • Ngay lập tức chế độ cuộc gọi: 4 * 32 bit cho mỗi đỉnh

+0

'Mảng chỉ mục: 16 bit trên mỗi đỉnh của VS. 'Chế độ gọi ngay lập tức: 4 * 32 bit trên mỗi đỉnh 'Không có tính toán sai, bởi vì với mảng đỉnh bạn cũng phải gửi dữ liệu đỉnh.Cho phép nói rằng tôi gửi glVertex3f (1,1,1) nó sẽ mất 3 * 32 bit + 32 bit cho địa chỉ chức năng? nhưng với mảng đỉnh, tôi cũng phải gửi x, y, z trong đó có 3 * 32 bit + chỉ số, trong đó có 16 bit, tổng số bit đã lưu = 16? Hay tôi đã bỏ lỡ điều gì? Theo như tôi biết bạn không thể lưu trữ các mảng đỉnh vào GPU, vì vậy bạn phải gửi dữ liệu đỉnh mỗi khung một lần nữa và một lần nữa ngay cả khi nó không thay đổi ...? – Newbie

+0

Sử dụng vertex Buffer Object vertex array thực sự được lưu trữ trong bộ nhớ GPU. Nếu không sử dụng VBO một cách rõ ràng các trình điều khiển hiện đại nhất có xu hướng tạo ra chúng tại chỗ, bởi vì đó là cách GPU hiện đại hoạt động. – datenwolf

+0

tại chỗ? ý của bạn là gì, GPU hiện đại chuyển đổi tất cả các mảng đỉnh thành VBO một cách tự động? – Newbie

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