Cách nhanh nhất để kết xuất các dòng bằng AA, độ dày khác nhau trong DirectX


14

Vì vậy, tôi đang thực hiện một số phát triển DirectX, sử dụng chính xác SharpDX trong .NET (nhưng các giải pháp API DirectX / C ++ có thể áp dụng được). Tôi đang tìm cách nhanh nhất để kết xuất các đường trong phép chiếu trực giao (ví dụ: mô phỏng vẽ đường 2D cho các ứng dụng khoa học) bằng DirectX.

Ảnh chụp màn hình các loại cốt truyện tôi đang cố gắng hiển thị như sau: nhập mô tả hình ảnh ở đây

Không có gì lạ khi các loại ô này có các dòng có hàng triệu phân đoạn, có độ dày thay đổi, có hoặc không có khử răng cưa trên mỗi dòng (hoặc bật / tắt toàn màn hình AA). Tôi cần cập nhật các đỉnh cho các dòng rất thường xuyên (ví dụ 20 lần / giây) và giảm tải càng nhiều cho GPU càng tốt.

Cho đến nay tôi đã thử:

  1. Kết xuất phần mềm, ví dụ GDI + thực sự không có hiệu năng kém nhưng rõ ràng là nặng về CPU
  2. API Direct2D - chậm hơn GDI, đặc biệt là với tính năng Khử răng cưa
  3. Direct3D10 sử dụng phương pháp này để mô phỏng AA bằng cách sử dụng màu đỉnh và phần tử ở phía CPU. Cũng chậm (tôi đã mô tả nó và 80% thời gian dành cho việc tính toán các vị trí đỉnh)

Đối với phương pháp thứ 3, tôi đang sử dụng Bộ đệm Vertex để gửi một dải tam giác đến GPU và cập nhật cứ sau 200ms với các đỉnh mới. Tôi đang nhận được tốc độ làm mới khoảng 5FPS cho 100.000 phân khúc dòng. Tôi cần hàng triệu lý tưởng!

Bây giờ tôi đang nghĩ rằng cách nhanh nhất sẽ là thực hiện việc xử lý GPU, ví dụ như trong Shader Geometry. Tôi có thể gửi các đỉnh dưới dạng một danh sách dòng hoặc đóng gói trong một kết cấu và giải nén trong Geometry Shader để tạo các hình tứ giác. Hoặc, chỉ cần gửi các điểm thô đến trình đổ bóng pixel và thực hiện vẽ Bresenham Line hoàn toàn trong trình tạo bóng pixel. HLSL của tôi bị rỉ sét, shader model 2 từ năm 2006 vì vậy tôi không biết về những thứ điên rồ mà GPU hiện đại có thể làm được.

Vì vậy, câu hỏi là: - đã có ai làm điều này trước đây chưa, và bạn có gợi ý nào để thử không? - Bạn có bất kỳ đề xuất nào để cải thiện hiệu suất với hình học cập nhật nhanh chóng (ví dụ: danh sách đỉnh mới cứ sau 20ms) không?

CẬP NHẬT ngày 21 tháng 1

Kể từ đó, tôi đã triển khai phương thức (3) bằng cách sử dụng các trình tạo bóng Geometry bằng cách sử dụng Bộ đệm LineStrip và Dynamic Vertex. Bây giờ tôi đang nhận được 100FPS tại 100 nghìn điểm và 10FPS tại 1.000.000 điểm. Đây là một cải tiến lớn nhưng hiện tại tôi đang lấp đầy tỷ lệ và tính toán hạn chế, vì vậy tôi đã suy nghĩ về các kỹ thuật / ý tưởng khác.

  • Điều gì về Instance Phần cứng của hình học Phân đoạn Đường?
  • Sprite Batch thì sao?
  • Còn các phương pháp định hướng (Pixel shader) khác thì sao?
  • Tôi có thể loại bỏ GPU hoặc CPU một cách hiệu quả không?

Nhận xét và đề xuất của bạn đánh giá cao nhiều!


1
Điều gì về AA bản địa trong Direct3D?
API-Beast

5
Bạn có thể chỉ ra một vài đường cong ví dụ mà bạn muốn vẽ không? Bạn đề cập đến một triệu đỉnh nhưng màn hình của bạn có thể không có nhiều hơn một triệu pixel , số lượng đó có thực sự cần thiết không? Dường như với tôi rằng bạn sẽ không cần mật độ dữ liệu đầy đủ ở mọi nơi. Bạn đã xem xét LOD chưa?
sam hocevar

1
Cách tiếp cận thứ hai mà bạn liên kết có vẻ tốt, bạn đang sử dụng bộ đệm đỉnh động mà bạn cập nhật hoặc bạn có tạo một cái mới mỗi lần không?

1
Có lẽ bạn nên đi với bộ đệm đỉnh động (không phải làm việc nhiều, chỉ cần nói với bộ đệm đỉnh của bạn là động, ánh xạ bộ đệm, sao chép dữ liệu của bạn qua, bỏ sơ đồ) nhưng nếu nút cổ chai của bạn là thế hệ đỉnh ở vị trí đầu tiên, thì có lẽ đã thắng Bây giờ tôi sẽ giúp nhiều. Đừng nghĩ có gì điên rồ khi sử dụng GS để giảm tải cho CPU

1
Nếu số lượng đỉnh cuối cùng quá lớn so với GPU, bạn vẫn có thể thử giảm tốc độ lấy mẫu của mình - bạn thực sự không cần hàng trăm triệu phân đoạn cho một đường cong khi màn hình của bạn sẽ rộng vài nghìn pixel nhất.

Câu trả lời:


16

Nếu bạn chỉ hiển Y = f(X)thị biểu đồ, thì tôi khuyên bạn nên thử phương pháp sau.

Dữ liệu đường cong được truyền dưới dạng dữ liệu kết cấu , làm cho nó bền bỉ và cho phép cập nhật một phần thông qua glTexSubImage2D. Nếu bạn cần cuộn, bạn thậm chí có thể thực hiện bộ đệm tròn và chỉ cập nhật một vài giá trị trên mỗi khung. Mỗi đường cong được hiển thị dưới dạng một quad toàn màn hình và tất cả công việc được thực hiện bởi pixel shader.

Nội dung kết cấu một thành phần có thể trông như thế này:

+----+----+----+----+
| 12 | 10 |  5 | .. | values for curve #1
+----+----+----+----+
| 55 | 83 | 87 | .. | values for curve #2
+----+----+----+----+

Công việc của trình đổ bóng pixel như sau:

  • tìm tọa độ X của đoạn hiện tại trong không gian tập dữ liệu
  • lấy ví dụ 4 điểm dữ liệu gần nhất có dữ liệu; ví dụ nếu giá trị X là 41.3nó sẽ chọn 40, 41, 4243.
  • truy vấn kết cấu cho 4 giá trị Y (đảm bảo bộ lấy mẫu không có nội suy bất kỳ loại nào)
  • chuyển đổi các X,Ycặp thành không gian màn hình
  • tính khoảng cách từ đoạn hiện tại đến ba đoạnbốn điểm
  • sử dụng khoảng cách làm giá trị alpha cho đoạn hiện tại

Bạn có thể muốn thay thế 4 bằng các giá trị lớn hơn tùy thuộc vào mức thu phóng tiềm năng.

Tôi đã viết một shader GLSL rất nhanh và bẩn khi thực hiện tính năng này . Tôi có thể thêm phiên bản HLSL sau, nhưng bạn sẽ có thể chuyển đổi nó mà không cần quá nhiều nỗ lực. Kết quả có thể được nhìn thấy dưới đây, với các kích cỡ dòng và mật độ dữ liệu khác nhau:

đường cong

Một lợi thế rõ ràng là lượng dữ liệu được truyền đi rất thấp và số lượng ngăn kéo chỉ là một.


Đó là một kỹ thuật khá tuyệt - tôi đã thực hiện GPGPU trước đây để đóng gói họa tiết với dữ liệu là thứ tôi biết, nhưng không phải là thứ tôi đã cân nhắc cho việc này. Kích thước lớn nhất (ví dụ: tập dữ liệu lớn nhất bạn có thể tải lên?). Tôi sẽ tải xuống mã của mình nếu bạn không phiền và chơi xung quanh nó - Tôi rất muốn xem hiệu suất.
Bác sĩ ABT

@ Dr.ABT Kích thước tập dữ liệu chỉ bị giới hạn bởi kích thước kết cấu tối đa. Tôi không thấy lý do tại sao hàng triệu điểm sẽ không hoạt động khi có bố cục dữ liệu phù hợp. Lưu ý rằng mã của tôi chắc chắn không phải là chất lượng sản xuất nhưng hãy liên hệ riêng với tôi nếu có bất kỳ vấn đề nào.
sam hocevar

Chúc mừng @SamHocevar - Tôi sẽ thử. Đã được một thời gian kể từ khi tôi biên soạn một tâm trí ví dụ OpenGL! :-)
Tiến sĩ ABT

Đánh dấu là câu trả lời, vì mặc dù tôi không sử dụng tải kết cấu, bạn đã trình bày một ví dụ OpenGL thực sự có thể vẽ các đường trên trình đổ bóng pixel và đưa chúng ta đi đúng hướng !! :)
Tiến sĩ ABT

4

Có một chương GPU Gems về kết xuất các dòng khử răng cưa: Các dòng được lọc sơ bộ nhanh . Ý tưởng cơ bản là kết xuất mỗi phân đoạn dòng thành một hình tứ giác và tính toán, tại mỗi pixel, một hàm Gaussian của khoảng cách trung tâm pixel từ phân đoạn dòng.

Điều này không có nghĩa là vẽ mỗi phân đoạn dòng trong biểu đồ thành một hình tứ giác riêng biệt, nhưng trong D3D11, bạn chắc chắn có thể sử dụng trình đổ bóng hình học và / hoặc điều chỉnh để tạo ra các hình tứ giác, giảm lượng dữ liệu được truyền vào GPU xuống chỉ còn các điểm dữ liệu chúng tôi. Có lẽ tôi đã thiết lập các điểm dữ liệu dưới dạng StructuredBuffer để đọc bởi shader đỉnh / hình học, sau đó thực hiện một cuộc gọi vẽ chỉ định số lượng phân đoạn sẽ được vẽ. Sẽ không có bất kỳ bộ đệm đỉnh thực tế nào; trình tạo bóng đỉnh sẽ chỉ sử dụng SV_VertexID hoặc SV_InstanceID để xác định điểm dữ liệu nào cần xem xét.


Xin cảm ơn - vâng tôi biết về bài viết đó, không có mã nguồn với nó, thật không may :-( Tiền đề của GeoShader + FragShader dường như là người chiến thắng cho loại công việc này. Lấy dữ liệu cho GPU một cách hiệu quả sẽ là phần khó khăn!
Tiến sĩ ABT

Xin chào @NathanReed quay trở lại vấn đề này - nếu tôi đã sử dụng Geometry Shader hoặc di chuyển để vẽ các hình tứ giác, thì Point1 / Point2 là các đỉnh đối diện của một hình tứ giác, làm thế nào trong Pixel Shader tôi có thể tính khoảng cách đến đường giữa Pt1 & Pt2? Liệu pixel shader có kiến ​​thức về hình học đầu vào?
Bác sĩ ABT

@ Dr.ABT Các tham số của dòng toán học phải được gửi xuống bộ đổ bóng pixel thông qua các bộ nội suy. Các pixel shader không có quyền truy cập trực tiếp vào hình học.
Nathan Reed

Tôi thấy, điều này có thể được thực hiện bằng cách gửi kết quả đầu ra từ GeometryShader hoặc instaging không? Để có thêm tín dụng (nếu bạn quan tâm), tôi đã thêm một Q ở đây: gamedev.stackexchange.com/questions/47831/ mẹo
Tiến sĩ ABT

@ Dr.ABT Chính xác giống như cách phối hợp kết cấu, vectơ bình thường và tất cả các loại công cụ đó thường được gửi tới trình đổ bóng pixel - bằng cách viết các kết quả đầu ra từ trình tạo bóng đỉnh / hình học được nội suy và nhập vào trình đổ bóng pixel.
Nathan Reed

0

@ Dr.ABT - Lời xin lỗi cho điều này là một câu hỏi, không phải là một câu trả lời. Tôi không tìm thấy cách nào để hỏi nó trong câu trả lời của Sam Hocevar ở trên.

Bạn có thể chia sẻ chi tiết hơn về cách cuối cùng bạn đã thực hiện các dòng cho biểu đồ của mình không? Tôi có cùng nhu cầu về một ứng dụng WPF. Cảm ơn trước cho bất kỳ chi tiết hoặc mã bạn có thể chia sẻ về điều này.


vì bạn biết đó không phải là câu trả lời, vui lòng chỉnh sửa và đặt nó dưới dạng nhận xét
MephistonX

Tôi đã cố gắng để làm điều đó nhưng không có nút "thêm bình luận" trên bài viết gốc.
ErcGeek

Xin chào ErcGeek, Xin lỗi tôi không thể chia sẻ giải pháp cuối cùng vì thông tin này là độc quyền của công ty tôi. Mặc dù các ví dụ và đề xuất ở trên đưa chúng ta đi đúng hướng. Tất cả tốt nhất!
Bác sĩ ABT

Bạn không thể gửi bình luận trước khi bạn đạt được một danh tiếng nhất định. Và tất cả các downvote này chắc chắn sẽ không cung cấp cho bạn cơ hội đó.
Mathias Lykkegaard Lorenzen

Anh chàng không nên bị phạt vì muốn biết kết quả cuối cùng và yêu cầu nó theo cách duy nhất có sẵn cho anh ta. Nâng cao câu trả lời.
David Chính
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.