WebGL 繪製Line的bug 二

2022-07-05 04:57:19 字數 3691 閱讀 1711

以兩個端點組成的線段為例,繪製line的時候只用指定兩個端點,如果通過三角形來模擬一條線段,則至少需要兩個三角形,如下圖:

這是兩個三角形模擬的線段。

因此要繪製一條線段,則需要六個頂點,兩個三角形;當時從上圖中,可以看出有些頂點是共享,實際上只需要四個頂點,然後通過索引的方式繪製兩個三角形,相信熟悉webgl的同學都理解這種通過索引來繪製的方式,此處不詳細說明。

如果要繪製兩條相連的線段呢,則需要增加兩個頂點,也就是6個頂點,繪製四個三角形,依次類推,繪製三條相連的線段需要8個頂點,繪製6個三角形;由此可以得出乙個結論,繪製有n個端點的line,需要:2 n 個頂點, (n-1) 2個三角形。

對於一條線段而言,控制的引數實際上只有兩個端點的座標和線的寬度。 

從上面的分析,我們知道了給定一系列點(n個)和線的寬度,繪製一條線段需要的頂點數是n * 2. 

當時 n個頂點資料應該如何計算得到呢? 先舉個簡單的2維繪圖的例子,現在假設給定了兩個端點:

(-50,0)和(50,0),要繪製一條寬度為2的線條,那麼總共是四個頂點,第乙個頂點是從第乙個端點 + 線寬造成的偏移量,線寬為2,所以偏移量的基數應該是2 / 2 = 1;

第二個頂點是從第乙個端點 + 線寬造成的偏移量 (-1),同樣線寬為2,所以偏移量的基數應該是2 /2 (-1) = -1;

依次類推,那麼應該如何偏移呢? 這個與線段的走向有關,示例中 線段的走向可以用第二個端點 - 第乙個端點計算出來:

(50,0) - (-50,0) = (100,0) ,歸一化之後就是(1,0),此為線段的方向向量,表示的線段的走向的是沿x軸正方向,對於第一頂點,偏移的方向應該是(1,0)逆時針旋轉90度,即和線段走向垂直的方向(與線段垂直的方向有兩個,此處基於右手法則,選擇逆時針旋轉90度的乙個),旋轉90度之後,向量程式設計了(0,-1)

從圖形學裡面的數學知識可以得知,向量(x,y)逆時針旋轉90度變成(-y,x);

對於第二個頂點,偏移的方向應該是(1,0)順時針旋轉90度,但是前面,我們已經把偏移的基數變成-1了,所以可以認為偏移的方向還是(1,0)逆時針旋轉90度,如圖:

基於線段方向計算頂點偏移方向

由此,可以得出第乙個頂點的位置是:

(-50,0) - (0,-1)* 1 = (-50,-1),

第二個頂點的位置是:

(-50,0)-(0,-1) * 1 = (-50,1)

對於第三,第四個頂點的計算也是類似的。

上面討論的是只有兩個端點的情況,事實上,如果是多個端點,以上討論的情況只適合多個端點中第乙個端點和最後乙個端點的情況,對於中間的端點,偏移的方向要綜合考慮這個端點連線的兩條線段的情況,同樣舉例說明:

假設三個端點的情況,三個端點 分別是 (-50,0),(0,0),(0,50),現在要計算第二個端點(0,0)對應的兩個頂點(第

三、第四個),如圖:

此時要計算中間的端點的兩個頂點位置,則需要考慮改端點連線的兩天線段的方向:

計算的大致思路,通過該端點的和前乙個端點相減 計算出第一條線段的方向:

(0,0) - (-50,0) = (50,0) = (1,0)(歸一化)

然後兩個方向向量相加,在旋轉逆時針旋轉90度,可以得到偏移的方向:

(1,0) + (0,1) = (1,1) = (0.707,0.707)(歸一化)

旋轉之後,偏移方向程式設計了(-0.707,0.707),

需要注意的是,此時的的偏移基數其實也是發生了變化的,拐角處的偏移量此時應該變成大了,即有了乙個放大因子。 可以通過 1 / 偏移方向 點乘 第一條線段的方向 來獲取這個放大因子,不過如果兩條線段夾角很小,點乘的值也很小,放大因子很大,為了拐角處的尖角不顯得是否大,我們一般限定放大因子不超過2. 因此公式可以變成:

1 / max(偏移方向 .  第一條線段的方向,0.5)

上面大量篇幅講述了如何計算頂點座標,事實上,前面文字所述的一切計算方法都是發生在頂點著色器中的,而且也只能在著色器中計算,因為最終顯示到螢幕上的頂點與鏡頭相關,上文中只是簡單的用了2維的情況模擬,如果在js端計算,將極大消耗效能。 (那你不是瞎扯嗎,我們都還沒搞清楚如何計算出要傳遞給頂點著色器的資料呢),其實不是瞎扯,因為只有搞清楚了在著色器中如何計算最終的頂點,才知道如何向頂點著色器中組織資料,

以上文中「多個端點的情況」的為例,我們可以總結出計算出乙個頂點需要哪些資料:

端點座標,偏移量,前乙個端點座標,後乙個端點座標

因此在著色器中需要定義四個attribute變數 position,offset,positionprev,positionnext,分別用來接收端點座標,偏移量,前乙個端點座標,後乙個端點座標。

對於前面兩頂點,其端點沒有前乙個端點,此時前乙個端點就取端點座標,然後在著色器中判斷 如果前乙個端點點座標 == 端點座標,則表明是第乙個端點;使用兩個端點的情況計算。

低於後面兩個頂點,其端點沒有後乙個端點,此時後乙個端點就取端點座標,然後在著色器中判斷 如果後乙個端點點座標 == 端點座標,則表明是最後乙個端點;使用兩個端點的情況計算。

對於中間的頂點,既存在端點座標,也存在前乙個端點的座標,和後乙個端點的座標,就使用前面多個端點的情況計算。

還是以之前三個端點的例子為例,三個端點的(50,0,0),(0,0,0),(0,50,0),線寬為2(注意此時已經是三維座標了,之前模擬的情況是用螢幕上的2維座標來模擬頂點在著色器中通過透視變換變成了二維座標的情況)

那麼第乙個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(50,0,0),2/2,       (50,0,0)                  (0,0,0)

第二個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(50,0,0),-2/2,       (50,0,0)                  (0,0,0)

第三個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(0,0,0),2/2,       (50,0,0)                  (0,50,0)

第四個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(0,0,0),-2/2,       (50,0,0)                  (0,50,0)

第五個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(0,50,0),2/2,       (0,0,0)                  (0,50,0)

第六個頂點的四個變數的資料分別是:

端點座標,      偏移量,  前乙個端點座標,後乙個端點座標

(0,50,0),-2/2,       (0,0,0)                  (0,50,0)

到此為止,我們知道了如何組織繪製需要的頂點的資料。

如果你對webgl 感興趣,可以了解下我們用webgl開發的3d機房專案:

無外掛程式純web 3d機房,html5+webgl傾力打造

WebGL 繪製Line的bug 三

之前鋪墊了許多,今天可以來分享點純乾貨了。bk.line3d function points,colors bk.line3d.prototype.computedata function if i 0 var idx 3 i var i2 i 2 offset i2 0 5 offset i2 1...

WebGL 繪製Line的bug 三

bk.line3d function points,colors elseelse else if aposition apositionnext else vec2 dira normalize currscreen prevscreen vec2 dirb normalize nextscree...

WebGL 繪製和變換

1.使用緩衝區物件向頂點著色器傳入多個頂點的資料,需要遵循以下五個步驟 1.1 建立緩衝區物件 gl.createbuffer 1.2 繫結緩衝區物件 gl.bindbuffer 1.3 將資料寫入緩衝區物件 gl.bufferdata 1.4 將緩衝區物件分配給乙個attribute變數 gl.v...