這里總結下幾種WebGL中實現遮罩的方法。
模板緩沖
模板緩沖可以實現渲染剔除,但是我們之前的學習里,剔除范圍是基於上一次渲染的結果,且上一次的渲染也會進行顯示,這樣的話並不適合用來實現遮罩。
我們想實現遮罩的話,是希望只繪制模板緩沖而不繪制顏色緩沖。
想要實現這樣的效果,可以借助 colorMask 方法來實現(如果關閉了顏色緩沖的所有通道后,下一次繪制就不會改變顏色緩沖了),具體寫法如下:
1 // 關閉顏色緩沖的所有通道 2 gl.colorMask(false, false, false, false); 3 // 繪制遮罩, 更新模板緩沖數據 4 gl.stencilFunc(gl.EQUAL, 1, 0xFF); 5 gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); 6 gl.drawElements(...); 7 gl.stencilFunc(gl.EQUAL, 1, 0xFF); 8 // 開啟顏色緩沖的所有通道 9 gl.colorMask(true, true, true, true); 10 // 繪制圖像, 受模板緩沖影響 11 gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); 12 gl.drawElements(...);
scissor
僅繪制指定的矩形區域,可以用來實現簡單的無旋轉遮罩。
使用着色器
傳入一張用來進行遮罩的圖片,通過着色器判斷這張圖片的像素值,來決定當前的像素是否需要丟棄,還是進行alpha值的改變,可以實現任意形狀的遮罩,缺點是對於較大的圖片會出現掉幀的情況。
使用混合
blendfunc實現的遮罩效果是最簡單的,首先繪制遮罩圖的,遮罩圖的blendfunc需要設置為:
mask:setBlendFunc(gl.ONE_MINUS_SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
然后繪制被遮罩對象,其blendfunc需要設置為:
sprite:setBlendFunc(gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA)
原理其實很簡單,遮罩圖繪制到framebuffer的時候只保留alpha值,而sprite繪制的時候使用遮罩的apha值。不過需要注意的是,如果使用該方法,需要保證opengl的Config中有配置alpha通道,例如在使用OpenGL ES的安卓環境中,需要設置
mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
否則,遮罩和圖都無法被繪制出來。
這種方法其實也有缺點,如果被遮罩對象是透明的話,是沒辦法和底下的混合的。