2015-07-10 99 views
8

我的任務是通過Stage3d(Adobe Flash)技術渲染二次貝塞爾曲線(路徑),該技術沒有任何擴展件(OpenGl擁有它),因爲我知道)。是的,有一個Starling-Extension-Graphics,但它使用簡單的方法將曲線段分割成許多直線,爲我的長曲線路徑生成很多三角形。在GPU上繪製二次曲線

所以..有一個完美的方式來呈現Loop和Blinn的獨立形狀。我讀過GPUGems3文章(gpugems3_ch25.html) 和移植是片段着色器AGAL2:

二次曲線的Pixel Shader

float4 QuadraticPS(float2 p : TEXCOORD0, 
    float4 color : COLOR0) : COLOR 
{ 
    // Gradients 
    float2 px = ddx(p); 
    float2 py = ddy(p); 
    // Chain rule 
    float fx = (2*p.x)*px.x - px.y; 
    float fy = (2*p.x)*py.x - py.y; 
    // Signed distance 
    float sd = (p.x*p.x - p.y)/sqrt(fx*fx + fy*fy); 
    // Linear alpha 
    float alpha = thickness - abs(sd); 
    if (alpha > 1)  // Inside 
    color.a = 1; 
    else if (alpha < 0) // Outside 
    clip(-1); 
    else     
    // Near boundary 
    color.a = alpha; 
    return color; 
} 

它的工作原理。但有兩個基本問題:

  1. 我不明白,算法:(我讀符號距離場,衍生物等...我想了很多的時間和再次讀取 - 但沒有!結果我的問題是:有誰幫我解釋一下在着色器發生了什麼(逐行(),如果可能的!)

  2. 的第二個問題是,曲線是在修剪?三角形的角落,並具有可變厚度。請看圖: https://monosnap.com/file/84EBOuQ1czNM5lprQ5VlnRUKP2mKmW 所以,如果我畫一個路徑,它看起來是這樣的:https://monosnap.com/file/54Zs5Xui6s3BL6lNdZRCx9ibcV2bCF

我喜歡通過使用每曲線段一個三角形的方法,因爲沒有任何幾何需要。我不需要有非常厚的曲線(1-2像素非常好),但厚度變化是一個問題。有誰能夠幫助我?

(對不起,我的英語。這不是我的母語。)

[由Spektre EDIT1]剛從評論和無效的答覆移動

我打算使用每一個三角形曲線段,像圖片上的

  • the path
  • 路徑由來自馬薩諸塞州紐約三角形每一個路徑段
  • 一個(二次曲線)
  • 如何使用這種方法處理問題,如果所有的控制點共線(趴在同一條直線)或近線的?
+0

添加細節,如該二次曲線你使用(方程式)每個曲線貼片上有多少個控制點,......這看起來像你正在使用三角形基元(厚度瑕疵的原因)可能是QUAD_STRIP會更好(其中控制點在定義的四邊形補丁內像quad這樣的方式是控制點不斷增大的四邊形,或者對於一般的曲線來說是棘手的)或者提供控制ol分別指定另一個屬性 – Spektre

+0

謝謝Spektre!我想畫出由3個控制點描述的任何二次貝塞爾曲線。現在我認爲最好的方法是:1.使用一個不變的放大四邊形(2個三角形)作爲「畫布」,在那裏我可以通過程序繪製任何東西2.找到具體的二次qurve方程(http://math.stackexchange .com/questions/1360891/find-quadratic-bezier-curve-equation-based-on-its-control-points)並將其傳遞給片段着色器而不是Loop/Blinn默認方程(u^2 -v = 0) 。 3.用Loop/Blinn算法繪製新的方程。 – Ilya

回答

6

對於3條控制點的Bezier曲線我將:

  1. 使用三角形基元
  2. 放大控制點包括圍繞曲線面積,以避免僞像

    triangle enlargement

這種方式很快,從A,B,C計算A',B',C'沒有問題,反之亦然。如果比例不變(例如scale=1.25),則最大可用曲線thickness<=2.0*min(|control_point-M|)*(scale-1.0)

爲了更安全的放大,您可以計算所需的精確比例尺(例如在幾何着色器中)並將其傳遞給頂點和片段...以上所有內容均可由幾何着色器完成。您應該使用透明度將曲線正確連接在一起。平均中間點應保持不變M=A+B+C=A'+B'+C'

如果透明度不是一個選項

然後,你需要改變的方法,使通過內部的紋理控制點和位置。

  1. 創建一個2D float紋理控制點

    • float pnt[9][N]
    • pnt[0,1,2][]是控制點A(x,y,z)
    • pnt[3,4,5][]是控制點B(x,y,z)
    • pnt[6,7,8][]是控制點C(x,y,z)
  2. 還創建1D顏色紋理

    • 類似rgba col[N]
    • 兩個紋理的x軸分辨率= N
  3. 現在繪製單四貝塞爾曲線的數量覆蓋整個屏幕

    並在片段着色器中檢查像素是否在任何曲線內。如果是,則輸出其顏色...

這可以得到高貝塞爾曲線非常緩慢算N

[EDIT1]幾乎總線的控制點

對於那些我會用四邊形

quad enlarge

  • D,E是鏡像點A,B周圍C
  • D=C+C-A
  • E=C+C-B
  • C是中點M = (A+B+D+E)/4 = C = (A'+B'+C'+D')/4
  • A',B',C',D'被放大A,B,D,E控制點
  • A'=C+(A -C)*scale
  • B'=C+(B -C)*scale
  • A =C+(A'-C)/scale
  • B =C+(B'-C)/scale

這可以用於任何貝塞爾不僅幾乎共線,但它使用更大的多邊形,所以這將是對性能較慢(以上片段則真的需要)

+0

非常感謝Spektre!這是夢幻般的!!!這就是我想的,但我寫不出來!它可能會工作得非常快! – Ilya

+0

嗯......我不明白爲什麼我需要使用透明度......你是什麼意思?第二種方法現在也不完全清楚......( – Ilya

+0

@伊利亞如果你只有單色貝塞爾曲線,那麼你不需要透明度,但你需要扔掉曲線未使用的碎片,否則三角形的空白區域(包含重疊/放大區域)將清除已經繪製的貝塞爾曲線... – Spektre