2016-05-06 21 views
10

Tôi cần vẽ một danh sách các hình dạng và tôi đang sử dụng Direct2D. Tôi nhận được danh sách các hình dạng từ một tập tin. Danh sách được sắp xếp và thứ tự của các phần tử bên trong tệp đại diện cho thứ tự các hình dạng này sẽ được vẽ. Vì vậy, ví dụ: nếu tệp chỉ định hai hình chữ nhật ở cùng một vị trí và với cùng kích thước, chỉ có hình chữ nhật thứ hai sẽ hiển thị (vì chữ đầu tiên sẽ bị ghi đè).Direct2D Depth Buffer

Với danh sách các hình dạng tôi proceede để vẽ nó theo cách sau:

list<Shape> shapes; 

for (const auto& shape : shapes) 
    shape.draw(); 

Nó là đơn giản để thấy rằng nếu tôi có hai hình dạng tôi không thể đảo ngược thứ tự của các hoạt động vẽ, và điều này có nghĩa là tôi phải chắc chắn rằng shape2 sẽ luôn được vẽ sau shape1 và cứ tiếp tục như vậy. Theo đó tôi không thể sử dụng nhiều chủ đề để vẽ hình dạng của tôi, và đây là một bất lợi lớn về mặt biểu diễn.

Tôi đọc Direct3D hỗ trợ bộ đệm độ sâu (hoặc z-buffer), chỉ định cho mỗi pixel tọa độ z của nó, sao cho chỉ các pixel "hiển thị" (các lực gần hơn với người xem) sẽ được vẽ, bất kể thứ tự các hình dạng được vẽ là. Và tôi có thông tin chi tiết về từng hình dạng khi tôi đọc tệp.

Có cách nào để sử dụng bộ đệm độ sâu trong Direct2D hoặc kỹ thuật tương tự cho phép tôi sử dụng nhiều chuỗi để vẽ hình dạng của mình không?

+0

Tôi không chắc chắn về bản thân 'Direct2D' - nhưng thông thường bạn sẽ gán hình dạng một điều phối' z', sắp xếp theo điều phối đó và sau đó render tương ứng, do đó thực hiện một bộ đệm Z đơn giản. – rhughes

+2

@ rhughes Tôi không cần phải sắp xếp chúng, vì đã được sắp xếp khi tôi đọc tệp. Ngoài ra, bằng cách sử dụng phương pháp này ngăn cản việc sử dụng nhiều chủ đề. – Nick

+0

Tôi có nghĩa là sắp xếp theo z-coord. Bạn không cần phải hiển thị chúng trên các luồng riêng biệt. Làm cho hình dạng với z-cood thấp nhất đầu tiên và sau đó làm việc theo cách của bạn để hình dạng với z-coord cao nhất. – rhughes

Trả lời

4

Có cách nào để sử dụng độ sâu bộ đệm trong Direct2D, hoặc một kỹ thuật tương tự cho phép tôi sử dụng nhiều luồng để vẽ các hình dạng của tôi?

Câu trả lời ở đây là không. Mặc dù thư viện Direct2D được xây dựng trên đầu Direct3D, nó không cung cấp cho người dùng tính năng như vậy thông qua API, vì các nguyên thủy bạn có thể vẽ chỉ được mô tả bằng các tọa độ hai chiều.Nguyên thủy cuối cùng mà bạn vẽ đến đích đích được đảm bảo để hiển thị, do đó không có kiểm tra độ sâu nào được thực hiện. Ngoài ra, bộ đệm sâu trong Direct3D không có nhiều việc phải làm với đa luồng trên phía CPU. Cũng cần lưu ý rằng ngay cả khi bạn đang phát hành lệnh vẽ bằng cách sử dụng nhiều luồng, chúng sẽ được tuần tự hóa bởi trình điều khiển Direct3D và được thực hiện tuần tự. Một số API đồ họa mới hơn như Direct3D 12Vulkan không cung cấp trình điều khiển đa luồng cho phép bạn vẽ hiệu quả nội dung khác nhau từ các luồng khác nhau nhưng chúng có độ phức tạp cao hơn.

Vì vậy, cuối cùng nếu bạn gắn bó với Direct2D, bạn còn lại với tùy chọn vẽ từng hình liên tục bằng một chuỗi đơn.

Nhưng những gì có thể được thực hiện là bạn có thể loại bỏ các hình dạng có hiệu quả bằng cách thử nghiệm để che mỗi hình dạng với tất cả những người khác. Vì vậy, các hình dạng occluded có thể được loại bỏ khỏi danh sách và không bao giờ trả lại ở tất cả. Bí quyết ở đây là một số hình dạng không lấp đầy hoàn toàn biên giới của chúng, do các vùng trong suốt (như văn bản) hoặc nếu hình dạng là một đa giác phức tạp. Các hình dạng như vậy không thể dễ dàng được kiểm tra hoặc sẽ cần các thuật toán phức tạp hơn.

Vì vậy, bạn phải lặp thourgh tất cả các hình dạng và nếu hình dạng hiện nay là một hình chữ nhật chỉ sau đó thực hiện kiểm tra tắc với tất cả các hình dạng trước vọt rects.

Mã sau đây nên được coi là mã giả, nó chỉ nhằm minh họa ý tưởng.

#define RECTANGLE 0 
#define TEXT  1 
#define TRIANGLE 2 
//etc 

typedef struct { 
    int type; //We have a type field 
    Rect bounds_rect; //Bounds rect 
    Rect coordinates; //Coordinates, which count vary according to shape type 
    //Probably you have many other fields here 
} Shape; 

//We have all shapes in a vector 
std::vector<Shape> shapes; 

Lặp lại tất cả các hình dạng.

for (int i=1; i<shapes.size; i++) { 
    if(shape[i].type != RECTANGLE) { 
    //We will not perform testing if the current shape is not rectangle. 
    continue; 
    } 

    for(int j=0; j<i; j++) { 
    if(isOccluded(&shape[j], &shape[i])) { 
     //shape[j] is totally invisible, so remove it from 'shapes' list 
    } 
    } 
} 

thử nghiệm Occlusion là một cái gì đó như thế này

bool isOccluded(Shape *a, Shape *b) { 
    return (a.bounds_rect.left > b.coordinates.left && a.bounds_rect.right < b.coordinates.right && 
      a.bounds_rect.top > b.coordinates.to && a.bounds_rect.bottom < b.coordinates.bottom); 
} 

Và bạn không cần phải lặp tất cả các hình dạng với một chủ đề duy nhất, bạn có thể tạo nhiều chủ đề để thực hiện các bài kiểm tra cho các bộ phận khác nhau của danh sách hình dạng . Tất nhiên bạn sẽ cần một số kỹ thuật khóa như mutex khi xóa các hình dạng khỏi danh sách, nhưng đó là một chủ đề khác.

0

Bộ đệm độ sâu được sử dụng để loại bỏ các phần tử gốc sẽ bị che khuất bởi một thứ gì đó ở phía trước trong không gian 3D, tiết kiệm thời gian vẽ lại bằng cách không làm phiền với những thứ không được nhìn thấy. Nếu bạn nghĩ về một cảnh với một cây nến cao, mỏng phía trước một quả bóng đối diện với máy ảnh, toàn bộ quả bóng không được rút ra và sau đó ngọn nến được vẽ lên nó, chỉ là các cạnh nhìn thấy được của quả bóng. Đây là cách sắp xếp bản vẽ không quan trọng

Tôi chưa nghe nói về việc sử dụng bộ đệm độ sâu trong D2D vì nó có phần vô nghĩa; tất cả mọi thứ được rút ra trên một mặt phẳng trong D2D, làm thế nào một cái gì đó có thể được ở phía trước hoặc phía sau cái gì khác? API có thể hỗ trợ nó nhưng tôi nghi ngờ nó vì nó không có ý nghĩa trừu tượng. Các thông tin chi tiết trên mỗi hình chỉ là để vẽ nó trong cơ bản mà bạn đã có

Thay vì những gì bạn có thể làm, phân chia và phân bổ hình dạng của bạn để đề của bạn trong khi giữ gìn trật tự, tức là

t1 { shape1, shape2, shape3 } = shape123 
t2 { shape4, shape5, shape6 } = shape456 
... 

Và vẽ các hình dạng vào một đối tượng mới (nhưng không phải là backbuffer), tùy thuộc vào lớp hình dạng của bạn, bạn có thể thể hiện kết quả dưới dạng một hình dạng. Điều này sẽ để lại cho bạn với nhiều hình dạng mà vẫn còn theo thứ tự nhưng đã được tính toán song song. Sau đó bạn có thể dần dần soạn kết quả cuối cùng của bạn bằng cách vẽ các kết quả theo thứ tự, tức là

t1 { shape123, shape456, shape789 } 
t2 { shape101112, shape131415 } 

t1 { shape123456789, shape101112131415 } = final shape 

Bây giờ bạn có hình dạng cuối cùng bạn chỉ có thể vẽ mà như bình thường

+0

Thủ tục của bạn có vẻ thực sự thú vị, nhưng trừ khi bạn chỉ định chính xác đối tượng mới này sẽ vẽ hình dạng ở đâu, toàn bộ quy trình có thể không khả thi. Hãy xem xét rằng tôi vẽ hình học cũng như dòng, hình elip, hình chữ nhật, văn bản (những cái này có thể được xử lý riêng). – Nick

+0

Bạn có thể vẽ mỗi 'hình dạng sáng tạo' thành một đối tượng kết cấu và sau đó kết hợp các kết cấu như trên vẽ kết quả cuối cùng vào một quad, điều này sẽ cho phép bạn đại diện cho bất kỳ nguyên thủy nào (cho dù văn bản hoặc hình học hoặc hình ảnh khác) . Điều này có thể yêu cầu một số delving vào d3d tuy nhiên, tôi không chắc chắn tuy nhiên d2d rộng lớn là – Madden

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