Cách lưu trữ tài nguyên trong hệ thống kết xuất homebrew của tôi


10

Lý lịch:

Tôi đang thiết kế một hệ thống kết xuất 3D đơn giản cho kiến ​​trúc kiểu hệ thống thành phần thực thể bằng C ++ và OpenGL. Hệ thống bao gồm một trình kết xuất và biểu đồ cảnh. Khi tôi hoàn thành lần lặp đầu tiên của trình kết xuất, tôi có thể phân phối biểu đồ cảnh vào kiến ​​trúc ECS. Bây giờ nó là giữ chỗ bằng cách này hay cách khác. Nếu có thể, sau đây là các mục tiêu của tôi cho trình kết xuất:

  1. Đơn giản . Đây là một dự án nghiên cứu và tôi muốn có thể dễ dàng thay đổi và mở rộng các hệ thống của mình (do đó là phương pháp ECS).
  2. Hiệu suất . Cảnh của tôi có thể có nhiều mô hình nhỏ và khối lượng lớn với nhiều hình học. Không thể chấp nhận để có được các đối tượng từ bối cảnh OGL và hình học bộ đệm mỗi khung hình kết xuất. Tôi đang nhắm đến địa phương dữ liệu để tránh bỏ lỡ bộ nhớ cache.
  3. Linh hoạt . Nó phải có khả năng hiển thị các họa tiết, mô hình và khối lượng (voxels).
  4. Tách rời . Biểu đồ cảnh có thể được tái cấu trúc vào kiến ​​trúc ECS cốt lõi sau khi tôi viết trình kết xuất.
  5. Mô-đun . Sẽ thật tuyệt khi có thể trao đổi trong các trình kết xuất khác nhau mà không thay đổi biểu đồ cảnh của tôi.
  6. Độ trong suốt tham chiếu , nghĩa là tại bất kỳ thời điểm nào tôi cũng có thể cung cấp cho nó bất kỳ cảnh hợp lệ nào và nó sẽ luôn hiển thị cùng một hình ảnh cho cảnh đó. Mục tiêu này đặc biệt không nhất thiết phải có. Tôi nghĩ rằng nó sẽ giúp đơn giản hóa việc tuần tự hóa cảnh (tôi sẽ cần có khả năng lưu và tải cảnh) và cho phép tôi linh hoạt để trao đổi trong các cảnh khác nhau trong thời gian chạy cho mục đích thử nghiệm / thử nghiệm.

Vấn đề và ý tưởng:

Tôi đã đưa ra một số cách tiếp cận khác nhau để thử nhưng tôi đang vật lộn với cách lưu trữ tài nguyên OGL (VAO, VBO, shader, v.v.) cho mỗi nút kết xuất. Sau đây là các khái niệm bộ nhớ đệm khác nhau mà tôi đã nghĩ đến cho đến nay:

  1. Bộ nhớ cache tập trung. Mỗi nút cảnh có một ID và trình kết xuất có bộ đệm ánh xạ ID để kết xuất các nút. Mỗi nút kết xuất chứa VAO và VBO được liên kết với hình dạng. Một bộ nhớ cache bỏ qua các tài nguyên và ánh xạ hình học đến một nút kết xuất trong bộ đệm. Khi hình học được thay đổi, một cờ bẩn được thiết lập. Nếu trình kết xuất nhìn thấy một cờ hình học bẩn trong khi lặp qua các nút cảnh, nó sẽ từ chối dữ liệu bằng nút kết xuất. Khi một nút cảnh bị loại bỏ, một sự kiện được phát ra và trình kết xuất sẽ loại bỏ nút kết xuất được liên kết khỏi bộ đệm trong khi giải phóng tài nguyên. Ngoài ra, nút được đánh dấu để loại bỏ và trình kết xuất có trách nhiệm loại bỏ nó. Tôi nghĩ rằng cách tiếp cận này gần như đạt được mục tiêu 6 trong khi cũng xem xét 4 và 5. 2 phải chịu sự phức tạp thêm và mất địa phương dữ liệu với tra cứu bản đồ thay vì truy cập mảng.
  2. Bộ nhớ cache phân tán . Tương tự ở trên, ngoại trừ mỗi nút cảnh có một nút kết xuất. Điều này bỏ qua việc tra cứu bản đồ. Để giải quyết địa phương dữ liệu, các nút kết xuất có thể được lưu trữ trong trình kết xuất. Sau đó, các nút cảnh thay vào đó có thể có các con trỏ để kết xuất các nút và trình kết xuất sẽ đặt con trỏ vào một lỗi bộ đệm. Tôi nghĩ rằng kiểu này bắt chước một cách tiếp cận thành phần thực thể, vì vậy nó sẽ phù hợp với phần còn lại của kiến ​​trúc. Vấn đề ở đây là bây giờ các nút cảnh giữ dữ liệu cụ thể của trình kết xuất. Nếu tôi thay đổi cách mọi thứ được hiển thị trong trình kết xuất (như kết xuất họa tiết so với âm lượng), bây giờ tôi cần thay đổi nút kết xuất hoặc thêm nhiều "thành phần" vào nút cảnh (cũng có nghĩa là thay đổi biểu đồ cảnh). Về mặt tích cực, đây có vẻ như là cách đơn giản nhất để có được trình kết xuất lặp đầu tiên của tôi và chạy.
  3. Siêu dữ liệu phân tán . Một thành phần siêu dữ liệu bộ đệm kết xuất được lưu trữ trong mỗi nút cảnh. Dữ liệu này không dành riêng cho việc triển khai mà chỉ chứa ID, loại và bất kỳ dữ liệu nào khác có liên quan cần thiết cho bộ đệm. Sau đó, việc tra cứu bộ đệm có thể được thực hiện trực tiếp trong một mảng bằng ID và loại có thể chỉ ra loại phương pháp kết xuất nào sẽ sử dụng (như spites so với volume).
  4. Lượt truy cập + ánh xạ phân tán . Trình kết xuất là khách truy cập và các nút cảnh là các thành phần trong mẫu khách truy cập. Mỗi nút cảnh giữ một khóa bộ đệm (như siêu dữ liệu nhưng chỉ là ID) mà chỉ trình kết xuất thao tác. ID có thể được sử dụng cho mảng thay vì tra cứu bản đồ tổng quát. Trình kết xuất có thể cho phép nút cảnh gửi một chức năng kết xuất khác dựa trên loại của nút cảnh và ID có thể được sử dụng bởi bất kỳ bộ đệm nào. ID mặc định hoặc ngoài phạm vi sẽ biểu thị lỗi bộ nhớ cache.

Làm thế nào bạn sẽ giải quyết vấn đề này? Hay bạn có bất cứ đề nghị? Cảm ơn đã đọc bức tường văn bản của tôi!


1
Bạn đã có tiến bộ gì chưa?
Andreas

Đây là một câu hỏi cực kỳ phức tạp và có lẽ nên được chia thành nhiều câu hỏi riêng biệt. Điều này về cơ bản là hỏi "Tôi nên thiết kế động cơ của mình như thế nào?" Lời khuyên của tôi sẽ là thiết kế một cái gì đó hỗ trợ các thành phần đơn giản trước, sau đó thêm và cấu trúc lại các tính năng khi bạn đi. Ngoài ra, hãy tra cứu sách thiết kế công cụ trò chơi 3D, trong đó sẽ bao gồm rất nhiều thông tin bạn đang tìm kiếm.
Ian Young

Câu trả lời:


2

Sau khi đọc lại câu hỏi của bạn, tôi cảm thấy mạnh mẽ rằng bạn đang khắc phục vấn đề. Đây là lý do tại sao:

  1. Thực tế chỉ có hai loại hệ thống kết xuất: Chuyển tiếp và Trì hoãn, không có loại nào phụ thuộc vào biểu đồ cảnh.

  2. Các vấn đề hiệu năng duy nhất bạn thực sự nên có với bất kỳ hệ thống kết xuất nào, phải đến từ số poly cao, và mã trình đổ bóng và mã máy khách không hiệu quả.

  3. Bộ nhớ cache thực sự làm giảm hiệu suất, nhưng chúng không hoàn toàn là những con quái vật mà bạn có thể nghĩ chúng là. 80% cải tiến hiệu suất của bạn sẽ đến từ một thuật toán hiệu quả hơn. Đừng phạm sai lầm tối ưu hóa trước mã của bạn.

Mà nói:

Nếu bạn đang sử dụng một khung cảnh homebrew thì bạn nên sử dụng giao diện "Trình kết xuất" (hoặc lớp cơ sở) để thiết kế phần kết xuất của mã cảnh báo của bạn. Mẫu khách truy cập sử dụng công văn kép là một cách tiếp cận tốt, vì bạn cũng có thể sử dụng nhiều loại nút biểu đồ như màu sắc, kết cấu, lưới, biến đổi, v.v ... Theo cách này, trong chu kỳ kết xuất, tất cả các trình kết xuất phải làm là đi bộ theo chiều sâu cấu trúc cây cảnh, vượt qua chính nó như là một đối số. Theo cách này, trình kết xuất về cơ bản chỉ là một tập hợp các shader và có thể là một hoặc hai bộ đệm khung. Kết quả của điều này là mã tìm kiếm / loại bỏ không còn cần thiết cho hệ thống kết xuất, chỉ là bản đồ chính.

Chắc chắn có nhiều cách khác để giải quyết các vấn đề bạn gặp phải, nhưng tôi không muốn đưa ra câu trả lời quá dài. Vì vậy, lời khuyên tốt nhất của tôi là hãy làm một cái gì đó đơn giản trước tiên, sau đó mở rộng nó để tìm ra điểm yếu của nó, sau đó thử nghiệm các phương pháp khác và xem điểm mạnh / điểm yếu của chúng nằm ở đâu trong thực tế.

Sau đó, bạn sẽ được đặt tốt để đưa ra quyết định sáng suốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.