模糊效果在遊戲中常常會用到,有的爲了突出前景會把背景給模糊化,有的是由於一些技能須要模糊效果。模糊是shader中較爲簡單的一種應用。cocos2dx 3.x給的demo中,就有sprite的模糊的效果。node
先說下這個模糊算法的大體思路,咱們在片斷着色器中能夠獲得當前像素點的顏色值,要想讓這個顏色變得模糊,就要讓它與它周圍的像素點的顏色稍微接近一點,那麼咱們就須要拿到這個像素點周圍的像素點的顏色值,咱們把這些個像素點的值加起來取平均值,就獲得了一個區域內的平均顏色。
若是直接使用這個顏色的話,最終的效果會變得很模糊,若是咱們只是想稍微模糊一點的話,就要讓這個平均值更接近於當前像素點本來的顏色,爲此,咱們取均值的時候對每一個像素點增長了一個權重的定義,當前像素點的權重最高,依次向周圍減弱,使得最後獲得的均值的顏色更接近於當前像素點原始的顏色。算法
看代碼:函數
#ifdef GL_ES precision mediump float; #endif varying vec4 v_fragmentColor; varying vec2 v_texCoord; uniform vec2 resolution;//模糊對象的實際分辨率 uniform float blurRadius;//半徑 uniform float sampleNum;//間隔的段數 vec4 blur(vec2); void main(void) { vec4 col = blur(v_texCoord); //* v_fragmentColor.rgb; gl_FragColor = vec4(col) * v_fragmentColor; } vec4 blur(vec2 p) { if (blurRadius > 0.0 && sampleNum > 1.0) { vec4 col = vec4(0); vec2 unit = 1.0 / resolution.xy;//單位座標 float r = blurRadius; float sampleStep = r / sampleNum; float count = 0.0; //遍歷一個矩形,當前的座標爲中心點,遍歷矩形中每一個像素點的顏色 for(float x = -r; x < r; x += sampleStep) { for(float y = -r; y < r; y += sampleStep) { float weight = (r - abs(x)) * (r - abs(y));//權重,p點的權重最高,向四周依次減小 col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight; count += weight; } } //獲得實際模糊顏色的值 return col / count; } return texture2D(CC_Texture0, p); }
精度限定符和varying
變量等的一些基礎的知識在前面的博客中遇到的已經說過。
uniform
變量是頂點着色器和片斷着色器共享使用的變量,uniform
的值不能被改變。
uniform
變量是由宿主程序設置的,代碼以下:code
void EffectBlur::setTarget(EffectSprite *sprite) { Size size = sprite->getTexture()->getContentSizeInPixels(); _glprogramstate->setUniformVec2("resolution", size); #if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) _glprogramstate->setUniformFloat("blurRadius", _blurRadius); _glprogramstate->setUniformFloat("sampleNum", _blurSampleNum); #endif }
這裏宿主程序設置了resolution
,blurRadius
和sampleNum
三個uniform
變量。渲染的時候,頂點着色器和片斷着色器均可以用到這三個變量的值。
resolution
是當前渲染node的實際分辨率。
blurRadius
是像素點模糊處理的參考矩形的半徑
sampleNum
選擇像素點的間隔的數量,相鄰像素點的間距等於blurRadius / sampleNum
orm
blur
函數就是計算該像素點的最終顏色,參數p
是當前像素點的座標,咱們以p
點爲中點以2r
爲邊長獲得一個矩形,這個矩形中每隔sampleStep
長度的像素點是當前像素點的顏色參考像素。每一個像素點會乘以一個weight
權重,這個weight
越靠近p
點值越高,目的是爲了讓最終的值更接近於p
點的像素顏色,而後各個像素點乘以權重後的顏色加起來,獲得col
,把各個權重也加起來獲得count
。最終的顏色值就是col/count
。對象
效果圖以下:
模糊前:
模糊後:
遊戲