WebGL 踩坑系列-1

WebGL 中的一些選項
WebGL 中開啓顏色混合(透明效果)
gl.enable(gl.BLEND);   
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

設置遮擋剔除有效。生成三角形時,沿着逆時針方向的那面會被生成出來,而另外一面就不會生成出來。git

gl.enable(gl.CULL_FACE); 
gl.cullFace(gl.BACK);

觀察球面的效果:github

 

當設置透明效果卻不開啓遮擋剔除的時候,用 web GL 生成球面,在球外觀察球面時就會看到一些奇怪的角。web

 第二個球就很明顯的有一些不一樣的部分。ide

 

在 web GL 中使用矩陣函數

能夠利用矩陣的平移、旋轉、縮放實現物體的各類動做。性能

我在最開始使用 Web GL 繪圖的時候,球面上的點都是利用循環獲得,可是因爲有縮放球面的需求,因此最開始的作法是測試

1. 建立緩衝區時用的 gl.DYNAMIC_DRAWthis

2. 當要縮放球面時,從新計算頂點spa

3. 用 gl.updateBufferData 函數更新定點數據3d

當縮放的時候就能明顯看到畫面撕裂,幀率降低。

可能的緣由是:

1. 每次從新計算都要使用大量的計算資源,若幀率爲 60,那麼每秒要計算上千個頂點,若是球面較精細,那麼須要計算的頂點數更多。

2. 而且每次計算以後都要將這些頂點傳入到 GPU 中,可能會佔用一部分的傳輸帶寬

正常的作法是用座標變換矩陣,將變換後的矩陣經過  gl.uniformMatrix4fv 傳入到着色器,就能夠輕鬆的實現平移旋轉和縮放。而且不會形成性能嚴重降低。

可是矩陣的乘法與普通的數乘有所差異,矩陣的乘法通常不知足交換律。

若 pMatrix 表示透視矩陣,vMatrix 表示視圖矩陣,mMatrix 表示模型矩陣,aVertex 表示傳入的頂點,那麼通常的乘式是

gl_Position = pMatrix * vMatrix * mMatrix * aVertex;

若是矩陣的順序不一樣,可能最後獲得的圖形也就不一樣。

 

對矩陣先進行旋轉操做,再進行平移操做。縮放操做的順序通常沒有影響。

但我在使用 gl-Matrix.js 時,對一個矩陣先進行旋轉,再進行平移操做:

1 mat4.identity(this.mMatrix); 2 
3 mat4.fromRotation(this.mMatrix, angle[1] * Math.PI*2, [0, 0, 1]); 4 mat4.rotate(this.mMatrix, this.mMatrix, angle[0] * Math.PI, [0, 1, 0]); 5 mat4.translate(this.mMatrix, this.mMatrix, pos); 6 
7 mat4.multiply(mvpMatrix, pvMatrix, this.mMatrix); 8 gl.uniformMatrix4fv(uniforms.pmv_matrix, false, mvpMatrix);

 

和將旋轉操做和平移操做放在兩個矩陣中進行獲得的結果並不相同。

1 mat4.identity(this.mMatrix); 2 
3 mat4.fromRotation(this.rMatrix, angle[1] * Math.PI*2, [0, 0, 1]); 4 mat4.rotate(this.rMatrix, this.rMatrix, angle[0] * Math.PI, [0, 1, 0]); 5 mat4.translate(this.mMatrix, this.mMatrix, pos); 6 mat4.mul(this.mMatrix, this.mMatrix, this.rMatrix); 7 
8 mat4.multiply(mvpMatrix, pvMatrix, this.mMatrix); 9 gl.uniformMatrix4fv(uniforms.pmv_matrix, false, mvpMatrix);

注意這裏用 pvMatrix 乘  mMatrix 以前先用 mMatrix 乘了一個附加矩陣 rMatrix

具體的緣由並不清楚,可是第二個操做實現的圖像符合個人需求。

 

=========================

這幾天又從新測試了下代碼,發現上面的旋轉平移操做的矩陣仍是有些問題,

具體問題在於通過旋轉平移後的面上反的,如下矩陣操做能夠方便的作到旋轉平移,而且獲得的面上正的

1 mat4.fromZRotation(this.rMatrix,         this.beta); // 繞 Z 軸旋轉 beta 角 2 mat4.rotateY(this.rMatrix, this.rMatrix, this.theta); // 再繞 Y 軸旋轉 theta 角 3 mat4.fromRotationTranslation(this.mMatrix, this.rMatrix, pos); 4 mat4.rotateZ(this.mMatrix, this.mMatrix, this.beta); 5 mat4.rotateY(this.mMatrix, this.mMatrix, this.theta);

最後獲得的面就是我想要的

 

完整的代碼能夠在個人 GitHub 上查看。

相關文章
相關標籤/搜索