Hỏi thuật toán kết xuất nhiều đối tượng đồ họa 3D

opengl

(Nguyễn G Huy) #1

Chào các bạn, cảm ơn các bạn đã ghé bài, vấn đề mình đang sử dụng OpenGL để làm Engine 3D nhỏ, và có tham khảo nhiều tài liệu trên mạng để tìm giải pháp để chỉ kết xuất các đối tượng nằm trong View Frustum nhưng không tìm được. Hôm nay đăng lên daynhauhoc mong các bạn có gợi ý cho mình Tree hay Algorithms !!!


(Tao Không Ngu.) #2

Hi Nguyễn G Huy.
Cũng đang nghiên cứu cái này mới đến bài shader. Theo mình thì xác định một khung bao rồi chiếu lên mặt phẳng 2d rồi cắt trên đó.
http://www.gameprogrammingpatterns.com/spatial-partition.html


(Red Sand) #3

Không có giải pháp chỉ kết xuất các đối tượng trong view frustum, muốn thì cũng tự code được, tính toán loằng ngoằng nhưng bỏ thời gian ra tí cũng được. Người ta không làm vì chi phí của vertex shading và geometry shading không lớn bằng pixel shading vì pixel shading chứa toàn bộ về ánh sáng & đổ bóng, chi phí dominate mấy cái kia. Pixel shading thì đã có kỹ thuật deferred shading chỉ tô các điểm ảnh đã được vẽ lên buffer, = các vật thể trong view frustum luôn. Hơn nữa nếu chỉ kết xuất các vật trong view frustum thì shadow mapping không chính xác.


(Florastamine) #4

Pixel shading thì shading kiểu nào cũng tô hết frustum cả, mà đến được khâu fragment thì đã culling test hết rồi. Nên deferred hay forward cũng không quan trọng (lợi thế mạnh nhất của deferred chỉ là giảm complexity của số lights xuống O(N)).

Thớt có thể tìm hiểu các kỹ thuật như portal culling (cũ, cũng gần gần BSP), occlusion culling, hoặc octree. Tóm tắt chung ở đây.


(Red Sand) #5

À đúng r, qua rasterization là cut hết ngoài view frustum rồi, sáng ra mơ ngủ @@


(Nguyễn G Huy) #6

Cảm ơn các bạn đã giúp mình!
Có thể câu hỏi của mình không rõ, nhưng mình đang tìm một giải pháp tối ưu trên CPU, ví dụ như một map game, có Hàng ngàn model (ở trong Model lại có vài ngàn Mesh), và ở mỗi khung hình mình phải duyệt từ đầu đến cuối và kết xuất hết tất cả.
std::vector<Renderable *> m_list;

Trong khi mình chỉ muốn kết xuất các đối tượng mà Camera nhìn thấy.


(Red Sand) #7

trong cụm từ “Camera nhìn thấy” đã bao gồm 3 thứ:

  • vị trí của camera
  • hướng của camera
  • vị trí của vertex
    Muốn đạt được “camera nhìn thấy” mà tránh 3 thứ này là điều không thể.

(Florastamine) #8

Ý bạn là duyệt scene và trả về những gì nằm trong vùng nhìn thấy của camera?

Nếu vậy thì thêm Renderable::IsInCameraView() để test vị trí của object có nằm ngoài view frustum của camera, rồi duyệt hết Renderable * trong scene (for (const auto &renderable : renderables) if (renderable->IsInCameraView()) ...) . Có thể bọc bounding box cho object để test nhanh hơn (vì phải test với 6 mặt phẳng của frustum).

Về cách test intersection: Tham khảo


(Nguyễn G Huy) #9

Đúng ý mình rồi bạn, cảm ơn bạn, vì mình thấy khi render, có nhiều object nằm ngoài camera rất phí.


(Florastamine) #10

Có lẽ bạn nhầm, nếu ý muốn bỏ những gì nẳm ngoài frustum (hoàn toàn hoặc 1 phần) thì nó đã được OpenGL làm tự động (xem lại modern OpenGL pipeline, phần clipping). Như hình dưới, 2 objects ở 2 bên trái/phải sẽ bị loại, còn chỉ những phần nằm trong frustum của 2 objects ở trên/dưới sẽ được render. Không cần tác động thêm từ C++ (trừ khi bạn muốn đếm số objects nằm trong frustum, thì dùng cách mình đã nói ở trên)
image

Cái mà bạn cần là làm sao để cắt những gì vẫn nằm trong frustum, nhưng player không thấy. Ví dụ:

Render bình thường:

Dù người chơi không thấy những gì nẳm phía sau cánh cửa, nhưng engine vẫn render chúng => overhead. Default clipping của OpenGL không xử lý được điều này, nó chỉ đơn giản là loại những gì nằm ngoài frustum. Để giải quyết điều này, post trên nữa của mình có đưa ra links.


(Nguyễn G Huy) #11

Cảm ơn bạn, do mình chưa vững căn bản!!!


83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?