2010-02-17 34 views
13

Làm cách nào để thay đổi độ dày của đường khi vẽ danh sách đường thẳng bằng Direct3D?Độ dày của đường Direct3D

This post nói rằng chiều rộng của đường không được hỗ trợ và tiếp tục cung cấp giải pháp thay thế. Sự lựa chọn khác?

Trong khi chúng tôi đang ở trong chủ đề này, các trình đổ bóng có cho phép người dùng vẽ các đường có mẫu gạch ngang không?

Trả lời

14

Bạn có thể sử dụng trình đổ bóng hình học để nhập dữ liệu vào một đoạn của đường và xuất một hình tam giác (một dải tam giác làm bằng hai hình tam giác) sao cho chiều rộng của tứ là không đổi trong không gian màn hình và khớp với mong muốn độ dày đường. Nó hoạt động hoàn hảo tốt (vì đã thực hiện nó trong một động cơ 3D CAD).

Nếu trình đổ bóng hình học không phải là một tùy chọn, giải pháp thay thế có thể là sử dụng trình đổ bóng đỉnh, nhưng nó sẽ yêu cầu một số công việc của VB của bạn. Hãy nhớ rằng VS phải có kiến ​​thức về phân đoạn trong toàn bộ nó, vì vậy bạn sẽ lưu trữ p và p + 1 cho mỗi phần tử VB của bạn, cộng với chi phí sao chép các chỉ số/đỉnh (tùy thuộc vào cấu trúc liên kết được sử dụng và nếu bạn hiển thị dòng của bạn dưới dạng nguyên thủy được lập chỉ mục hay không).

Nếu hiệu suất không phải là một vấn đề, việc mở rộng trên CPU có thể là cách để đi.

EDIT:

Về mẫu dash: bạn có thể sử dụng một Shader geometry quá để thi đua glLineStipple hành vi. Nếu bạn có cấu trúc liên kết GL_LINES, tức là nói các dòng riêng biệt, mẫu sẽ khởi động lại ở mỗi đoạn đường mới. Vì vậy, bạn chỉ cần tính toán trong trình đổ bóng hình học bắt đầu ngang không gian màn hình (hoặc bắt đầu theo chiều dọc, tùy theo hướng) của đoạn đường của bạn và chuyển thông tin bổ sung này cho trình đổ bóng pixel. Sau đó, trình đổ bóng pixel sẽ chịu trách nhiệm loại bỏ các đoạn theo các yếu tố yếu tốmẫu (DirectX 10/11 Integer và bitwise instructions giúp dễ dàng).

Một lần nữa điều này hoạt động tốt và bạn có thể kết hợp nó với các dòng chiều rộng mô phỏng (với kỹ thuật đầu tiên được đề cập ở trên).

Bây giờ, nếu bạn có GL_LINE_STRIP cấu trúc liên kết, mẫu sẽ khởi động lại ở mỗi nguyên thủy mới (vì vậy đối với mỗi cuộc gọi vẽ mới). Tình hình trở nên phức tạp hơn một chút vì bạn cần phải có kiến ​​thức về số lượng điểm ảnh đã được hiển thị trước đó và điều này cho mỗi đoạn đường.

Bạn có thể đạt được điều đó bằng cách hiển thị dải đường của bạn trong một VB tạm thời bằng chức năng phát trực tiếp DirectX 10 (mỗi phần tử của VB này tương ứng với chiều dài không gian màn hình của mỗi phân đoạn). Sau đó, bạn phải làm một tiền tố song song Sum (aka Scan) của VB này (để tích lũy từng giá trị độ dài đoạn đường).

Cuối cùng, bạn vẽ dải đường của mình như cho GL_LINES nhưng sử dụng thông tin thêm Quét VB này trong PS.

13

Độ dày của đường không chỉ không được Direct3D hỗ trợ, nhưng không được hỗ trợ bởi bất kỳ GPU hiện có nào. Không có GPU mà tôi biết rằng thậm chí có thể vẽ các đường thích hợp (tất cả các dòng giả bằng cách sử dụng các đa giác thoái hóa - tức là, đỉnh thứ hai và thứ ba ở cùng vị trí, vì vậy tam giác cơ bản sụp đổ thành một dòng duy nhất).

Mặc dù có thể đặt chiều rộng đường trong OpenGL, trình điều khiển OpenGL tạo quads được ép đùn (không được hỗ trợ bởi GPU hiện tại hoặc được mô phỏng bằng hai tam giác cho mỗi quad) để vẽ "đường" trên màn.

Vì vậy, có thể không có cách nào xung quanh việc tạo tứ giác ép đùn cho mục đích đó. Có một số cách để đạt được điều đó, như Stringer Bell giải thích trong câu trả lời của mình. Cách đơn giản nhất để làm việc với tôi là tạo ra một vertex buffer chứa mỗi đỉnh hai lần, với các normals trỏ "right" hoặc "left", tùy thuộc vào việc chúng là cạnh phải hay trái của đường kẻ. Các tính năng chính: Sau đó, một shader vertex rất đơn giản có thể thực hiện việc ép đùn (bằng cách thay đổi vị trí đỉnh bởi một bội số của vector thông thường của nó). Bằng cách này bạn có thể nhanh chóng thay đổi chiều rộng của đường, mà không phải tính toán lại hình học của bạn trên CPU. Điều này có thể hữu ích nếu bạn muốn điều chỉnh độ rộng của đường tùy thuộc vào kích thước hoặc khoảng cách của đối tượng.

+0

Đây là một giải pháp thú vị. Bạn đã đạt được để có được kết quả tương tự hơn với một cuộc gọi glLineWidth (trên cơ sở mỗi pixel)? – Stringer

+0

Tôi đã không kiểm tra nó trên mỗi pixel, nhưng đối với các dòng không được bảo vệ, chống răng cưa thì các kết quả phải tương tự nhau. Sử dụng texture (để mô phỏng các dạng stipple của OpenGL), chắc chắn sẽ đưa bạn vào thế giới đau đớn, với nội suy phi tuyến của tọa độ kết cấu (mà NVidia Quadros xử lý đáng ngạc nhiên xấu, thậm chí so với phần Geforce chủ yếu giống hệt nhau). Trình đổ bóng cần phải thực hiện rất nhiều công việc bổ sung để có được các quyền texcoords. – Pepor

+0

Bạn có thể tự mình thử, chỉ cần sử dụng một số loại "chiều dài dòng trong pixel màn hình" cho tọa độ kết cấu và vẽ các đường thẳng với kết cấu có mẫu hình trên đó. Bạn sẽ ngạc nhiên như thế nào không đồng đều mô hình. Ít nhất là tôi. ;-) – Pepor

0

Về mẫu gạch ngang của bạn (stippling) câu hỏi, đặt cược tốt nhất của bạn có lẽ là để làm cho dòng như một quad mỏng và áp dụng một kết cấu để nó trong pixel shader, nơi mà các kết cấu chứa mẫu gạch ngang của bạn. Bạn sẽ cần phải đặt chế độ địa chỉ mẫu để bọc, như sau:

SamplerState wrapTriLinear { 
    AddressU = WRAP; 
    AddressV = WRAP; 
} 
Các vấn đề liên quan