2010-02-17 103 views
13

如何在使用Direct3D繪製線條列表時更改線條的粗細?Direct3D線條厚度

This post表示不支持線寬並繼續提供解決方法。其他選項?

雖然我們在這個主題上,但是着色器允許用虛線模式畫線嗎?

回答

14

您可以使用幾何着色器將輸入線段作爲輸入並輸出一個四邊形(由兩個三角形組成的三角形條),以使四邊形的寬度在屏幕空間中保持不變,並匹配期望值線的粗細。它非常好地工作(在CAD 3D引擎中實現它)。

如果幾何着色器不是一個選項,解決方法可能是使用頂點着色器,但它需要一些VB的重新工作。請記住,VS必須掌握整個線段的知識,這樣您最終會爲每個VB元素存儲p和p + 1,並且還會存儲索引/頂點的重複成本(取決於所使用的拓撲和如果您將您的行渲染爲索引原語或不)。

如果性能不是問題,那麼在CPU上進行擴展可能是一種方法。

編輯:

關於短跑模式:你可以以模擬glLineStipple行爲使用幾何着色器了。 如果您有一個GL_LINES拓撲結構,也就是隔離的線路,該模式將在每個新線段重新開始。因此,您只需在幾何着色器中計算線段的屏幕空間水平開始(或垂直開始,取決於方向),並將此額外信息傳遞給像素着色器。然後像素着色器將負責根據因子模式值(DirectX 10/11 Integer和Bitwise指令使其變得容易)丟棄片段。

再次,這個效果很好,你可以將它與模擬的寬度線結合起來(使用上面提到的第一種技術)。

現在,如果您有GL_LINE_STRIP拓撲,則模式會在每個新基元處重新啓動(所以對於每個新繪製調用)。情況變得有點複雜,因爲您需要了解之前渲染的像素數量,以及每個線段的像素數量。

您可以通過使用DirectX 10流出功能(VB的每個元素對應於每個段的屏幕空間長度)在臨時VB中呈現線條來實現此目的。然後,您必須執行此VB的並行前綴和(又名掃描)(用於累計每個線段長度值)。

最後,您將渲染線條,如GL_LINES,但在PS中使用此額外的掃描VB信息。

13

線條粗細不僅不被Direct3D支持,它也不被任何現有的GPU支持。沒有我知道的GPU甚至可以繪製出合適的線條(它們都使用退化的多邊形僞造線條 - 也就是說,第二個和第三個頂點位於相同的位置,所以三角形基本上摺疊成一條線)。

儘管可以在OpenGL中設置線寬,但OpenGL驅動程序會創建拉伸的四邊形(目前GPU不支持,並且每個四邊形都使用兩個三角形進行仿真),以繪製「線條」屏幕。

所以可能沒有辦法爲此創建擠壓四邊形。正如Stringer Bell在他的回答中解釋的那樣,有幾種方法可以實現這一目標。

對我來說最簡單的方法是創建一個頂點緩衝區,它包含每個頂點兩次,法線指向「右」或「左」,具體取決於它們是線的右邊還是左邊。然後,一個非常簡單的頂點着色器可以執行擠出操作(通過將頂點位置更改爲其法向量的倍數)。這樣,您可以快速更改線寬,而無需重新計算CPU上的幾何圖形。如果要根據對象的大小或距離調整線寬,這可能很有用。

+0

這是一個有趣的解決方案。您是否獲得了與使用glLineWidth調用(基於每個像素)相同的結果? – Stringer 2010-02-18 14:22:35

+0

我沒有檢查每像素,但對於無紋理,反鋸齒的線條,結果應該足夠類似。使用紋理(例如模擬OpenGL的點畫模式)非常有把握讓你陷入一個痛苦的世界,其中紋理座標的非線性插值(即使與大多數相同的Geforce部分相比,NVidia Quadros的處理令人驚訝地不好)。着色器需要執行許多額外的工作才能正確使用texcoords。 – Pepor 2010-03-15 13:20:24

+0

您可以自己嘗試,只需使用某種「屏幕像素的線條長度」作爲紋理座標,然後在其上繪製點畫模式的紋理繪製線條。你會驚訝地發現圖案不均勻。至少我是。 ;-) – Pepor 2010-03-15 13:21:57

0

關於你的虛線樣式(點畫)的問題,最好的辦法可能是使該行,薄型四方和像素着色器,其中紋理包含您的虛線樣式應用紋理。您將需要設置採樣器地址模式來包裝,如:

SamplerState wrapTriLinear { 
    AddressU = WRAP; 
    AddressV = WRAP; 
}