2013-08-03 42 views
17

我有一些簡單的多邊形(少於20個頂點)在簡單的xy平面上使用GL_TRIANGLES和平面顏色進行2D模擬。使用片段着色器在2D多邊形上繪製邊框

我想爲這些多邊形添加可變厚度和不同顏色的邊框。我有使用相同的頂點和glLineWidth/GL_LINE_LOOP實現的東西,它可以工作,但是是另一個渲染過程並重復所有的頂點變換。

我想我應該可以在片段着色器中使用gl_FragCoord和頂點數據和/或紋理座標來做到這一點,但我不確定,而且我的天真嘗試顯然不正確。

我想像下面這樣。

uniform vec2 scale; // viewport h/w 
uniform float line_width; 
uniform vec4 fill_color; 
uniform vec4 border_color; 

varying vec4 vertex; // in world coords 

void main() 
{ 
    if (distance_from_edge(gl_FragCoord, vertex, scale) < line_width) 
    { 
     // we're close to the edge the polygon, so we're the border. 
     gl_FragColor = border_color; 
    } 
    else 
    { 
     gl_FragColor = fill_color; 
    } 
} 

我試圖找出的部分是distance_from_edge函數 - 如何計算?正在使用gl_FragCoord錯誤的方法 - 我應該使用某種紋理映射嗎?

作爲一個實驗,我試着用頂點將頂點轉換爲像素空間,然後計算像素與gl_FragCoord之間的距離,但這給出了我不太明白的奇怪結果。另外我需要的距離邊緣,而不是頂點,但我不知道如何得到這一點。

任何想法?

編輯:基於尼科爾的反應,我的問題是:

假設我有一個標記爲邊緣頂點3角落頂點的三角形,並在中間一個頂點標爲未EDGE(3個三角形所以呈現總計),那麼如何在片段着色器中插入以繪製給定厚度的邊界?我假設我將邊緣標誌傳遞給了片段着色器,以及所需的線條粗細,並且它會執行一些插值計算來計算邊緣與不是邊緣頂點之間的距離,並將顏色閾值限制爲邊框/填充?

+1

'gl_FragCoord'將是大規模對你無益。這只是告訴你片段在屏幕上的位置;它沒有說明碎片相對於三角形的位置。頂點位置同樣會大量無益。您將需要頂點着色器/用戶提供的數據的幫助,該數據根據頂點是否是頂點將頂點的值放入頂點,然後插值。這意味着你無法檢測到單個三角形的邊緣;您必須將三角形分成幾個三角形,以便區分內部頂點和邊緣頂點。 –

+0

謝謝,我懷疑我錯過了一些東西。所以如果我有一個帶有3個頂點的三角形標記爲邊緣頂點,並且中間的一個不是(用四個三角形渲染),那麼如何內插到邊界的給定線寬? – bloodearnest

回答

23

所有你需要的是重心座標,因爲你正在處理三角形。爲三角形的每個頂點分配一個標識,然後在頂點和片段階段之間使用硬件的內置插值來計算片段着色器中每個頂點的相對距離。

您可以將每個頂點的重心座標視爲與相對邊緣的距離。在下圖中,頂點P0的相對邊是e1,它的距離用h1表示;其重心座標是<0.0, h1, 0.0>。當光柵化過程中生成片段時,GPU可以在內部使用該座標空間來內插三角形的頂點屬性,這使得基於三角形內的位置對每個頂點屬性進行快速加權。

Diagram illustrating the calculation of distance from each edge

下面是兩個教程,解釋如何做到這一點,這通常是指用於渲染線框覆蓋,所以你可能有更好的運氣尋找那個。出於您的目的,由於這實際上是線框渲染的專門化(除了您想要排除不屬於外部多邊形邊線的線),您將需要識別邊頂點並執行其他處理。例如,如果頂點不是外部邊緣的一部分,那麼您將需要爲其分配類似於< 1,100,0>和連接頂點< 0,100,1>的重心座標,並且內部邊緣將會被忽略(假定它是一個與指定的頂點< 0,1,0>相反的邊,如下圖所示)。這個想法是,你永遠不需要沿着這條邊的一個點插入任何接近0.0的位置(或者你用來爲邊界的一部分着色一個片段的任何閾值),使它離三角形的中心非常遠離方向對面的頂點將解決這個問題。

Diagram showing how to exclude interior edges

無幾何着色器(OpenGL ES的友好):

這裏的解釋如何做到這一點,如果你可以修改你的頂點數據保持重心座標的鏈接。它具有較高的存儲和預處理要求(特別是,在相鄰邊之間共享頂點可能不再可行,因爲您需要每個三角形由三個頂點組成,每個頂點具有不同的輸入重心座標 - 這就是爲什麼幾何着色器是理想的解決方案)但是,它將運行在比更常見的需要幾何着色器的解決方案更多的OpenGL ES類硬件上。

http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/

隨着幾何着色器(的OpenGL ES型):

或者,您可以使用幾何着色器計算在看到了在渲染時每個三角形的重心座標本教程。很可能在OpenGL ES中,您將無法訪問幾何着色器,因此可能會忽略它。

http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_10.html http://strattonbrazil.blogspot.com/2011/09/single-pass-wireframe-rendering_11.html

該解決方案的理論基礎可以在這裏找到(互聯網檔案Wayback機器提供):

http://web.archive.org/web/ */http://cgg-journal.com/2008-2/06/index.html

+0

謝謝,這讓我走在正確的道路上。我已經實現了非幾何着色器線框,並且它工作得很好。現在我只需要添加額外的非周長頂點並適當標記。我已經在我自己的實驗中部分地沿着這條路線走下去了,但是有1個座標,而不是3個。 – bloodearnest

+3

理論基礎鏈接已關閉,此處爲[替代鏈接(web檔案)](https://web.archive。組織/網絡/ 20130607004602/HTTP://cgg-journal.com/2008-2/06/index.html)。來自同一家夥的另一篇論文:[隱藏線移除的抗鋸齒線框圖的兩種方法](http:// orbit.dtu。dk/fedora/objects/orbit:55459/datastreams/file_3735323/content) – fedab

+0

不幸的是,這種技術會導致邊界接近頂點的工件。內部三角形邊緣可以「切斷」邊界部分:http://imgur.com/Btl6h2Y。 – John