標籤:開啟 linear 步驟 定義 黃色 .com 一點 起點 過程
1.如何?霧化
實現霧化的方式由多種,這裡使用最簡單的一種:線性霧化(linear fog)。線上性霧化中,某一點的霧化程度取決於它與視點之間的距離,距離越遠霧化程度越高。線性霧化有起點和終點,起點表示開始霧化之處,終點表示完全霧化之處兩點之間某一點的霧化程度與該點與視點的距離呈線性關係。比終點更遠的點完全霧化了,即完全看不見了。
某一點霧化的程度可以被定義為霧化因子(fog factor),並線上性霧化公式中被計算出來:
<霧化因子> = (<終點> - <當前點與視點間的距離>) / (<終點> - <起點>)
這裡:
<起點> <= <當前點與視點間的距離> <= <終點>
霧化因子為1.0,表示該點完全沒有被霧化,可以很清晰地看到此處的物體。如果為0.0, 就表示改點完全被霧化了。起點因子的線形圖如下所示:
2.片元著色器中包含霧化因子的片元顏色計算
計算公式如下:
<片元顏色> = <物體表面顏色> * <霧化因子> + <霧化顏色> * (1 - <霧化因子>)
3.使用頂點的w分量作為當前點與視點間的距離
之前,我們並未顯示使用過gl_Position的w分量,實際上,這個w分量的值就是頂點的視圖座標的z分量乘以-1。在視圖座標系中,視點在原點,視線沿著Z軸負方向,觀察者看到的物體其視圖座標系值z分量都是負的,而gl_Position的w分量正好是z分量值乘以-1,所以可以直接使用該值來近似頂點和視點建的距離。
4.繪製圓形的點
為了將矩形削成圓形,需要知道每個片元在光柵化過程中的座標。在第5章的一個樣本程式中,在片元著色器中通過內建變數gl_FragCoord來訪問片元的座標。實際上,片元著色器還提供了另外一個內建變數gl_PointCoord。這個變數可以協助我們繪製圓形的點。片元著色器內建變數:
變數類型和名稱/描述
vec4 gl_FragCoord/片元在視窗座標
vec4 gl_PointCoord/片元在被繪製的點內的座標(從0.0到1.0)
gl_PointCoord座標值的區間從0.0到1.0,如所示。為了將矩形削成圓形,需要將與中心點(0.5, 0.5)距離超過0.5,也就是將圓外的片元剔除掉。在片元著色器中,可以使用discard語句來放棄當前片元。
在片元著色器中的代碼實現方式如下:
var FSHADER_SOURCE =‘#ifdef GL_ES\n‘ +‘precision mediump float;\n‘ +‘#endif\n‘ +‘void main(){\n‘ +‘ float distance = distance(gl_PointCoord, vec2(0.5, 0.5));\n‘ +‘ if (distance <= 0.5){\n‘ +‘ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n‘ +‘ }else{\n‘ +‘ discard;‘ +‘ }\n‘ +‘}\n‘;
5.α混合
我們要讓物體實現半透明,實現這種效果需要用到顏色的a分量。該功能被稱為a混合(alpha blending)或混合(blending),WebGL已經內建了該功能,值需要開啟即可。
如何?a混合?
1.開啟混合功能:gl.enable(gl.BLEND)。
2.指定混合函數:gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)。
如果我們只設定了顏色的第四個分量,是看不到透明效果的,必須要執行上面兩個步驟。
6.gl.blendFunc(src_factor, dst_factor)
通過參數src_factor和dst_factor指定進行混合操作的函數,混合後的顏色如下計算:
<混合後的顏色> = <源顏色> * src_factor + <目標顏色> * dst_factor
參數:
src_factor:指定源顏色在混合顏色重的權重因子,如下表所示
dst_factor:指定目標顏色在混合後顏色重的權重因子,如下表所示
常量/R分量的係數/G分量的係數/B分量的係數
gl.ZERO/0.0/0.0/0.0
gl.ONE/1.0/1.0/1.0
gl.SRC_COLOR/Rs/Gs/Bs
gl.ONE_MINUS_SRC_COLOR/(1-Rs)/(1-Gs)/(1-Bs)
gl.DST_COLOR/Rd/Gd/Bd
gl.ONE_MINUS_DST_COLOR/(1-Rd)/(1-Gd)/(1-Bd)
gl.SRC_ALPHA/As/As/As
gl.ONE_MINUS_SRC_ALPHA/(1-As)/(1-As)/(1-As)
gl.DST_ALPHA/Ad/Ad/Ad
gl.ONE_MINUS_DST_ALPHA/(1-Ad)/(1-Ad)/(1-Ad)
gl.SRC_ALPHA_SATUREATE/min(As,Ad)/min(As,Ad)/min(As,Ad)
上表中,(Rs,Gs,Bs, As)和(Rd,Gd,Bd,Ad)表示源顏色和目標顏色的各個分量。
假如源顏色是半透明的綠色(0.0, 1.0, 0.0, 0.4),目標顏色是普通的黃色(1.0, 1.0, 0.0, 1.0),調用函數:
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
計算過程如所示:
7.透明和不透明物體共存
在使用a混合功能時,我們屏蔽掉了隱藏面消除功能(去掉了代碼gl.enable(gl.DEPTH_TEST)。關閉隱藏面消除功能只是一個粗暴的解決方案,並不能滿足實際的需求。實際上,通過某些機制,可以同時實現隱藏面消除和半透明效果。我們只需要:
1.開啟隱藏面消除功能:gl.enable(gl.DEPTH_TEST)。
2.繪製所有不透明的物體(a為1.0)。
3.鎖定用於進行隱藏面消除的深度緩衝區的寫入操作,使之唯讀。調用:
gl.depthMask(false);
4.繪製所有半透明的物體(a小於1.0),注意他們應當按照深度排序,然後從後向前繪製。
5.釋放深度緩衝區,使之可讀可寫。調用:
gl.depthMask(true)
8.gl.depthMask(mask)
鎖定或釋放深度緩衝區的寫入操作。參數:
mask:指定是鎖定深度緩衝區的寫入操作(false),還是釋放之(true)
WebGL 進階技術