Cocos2d-x shader學習: 模糊(Blur)

模糊效果在遊戲中經常會用到,有的爲了突出前景會把背景給模糊化,有的是因爲一些技能需要模糊效果。模糊是shader中較爲簡單的一種應用。cocos2dx 3.x給的demo中,就有sprite的模糊的效果。

先說下這個模糊算法的大致思路,我們在片段着色器中可以得到當前像素點的顏色值,要想讓這個顏色變得模糊,就要讓它與它周圍的像素點的顏色稍微接近一點,那麼我們就需要拿到這個像素點周圍的像素點的顏色值,我們把這些個像素點的值加起來取平均值,就得到了一個區域內的平均顏色。 
如果直接使用這個顏色的話,最終的效果會變得很模糊,如果我們只是想稍微模糊一點的話,就要讓這個平均值更接近於當前像素點原本的顏色,爲此,我們取均值的時候對每個像素點增加了一個權重的定義,當前像素點的權重最高,依次向周圍減弱,使得最後得到的均值的顏色更接近於當前像素點原始的顏色。

看代碼:


 
  1. #ifdef GL_ES
  2. precision mediump float;
  3. #endif
  4.  
  5. varying vec4 v_fragmentColor;
  6. varying vec2 v_texCoord;
  7.  
  8. uniform vec2 resolution;//模糊對象的實際分辨率
  9. uniform float blurRadius;//半徑
  10. uniform float sampleNum;//間隔的段數
  11.  
  12. vec4 blur(vec2);
  13.  
  14. void main(void)
  15. {
  16. vec4 col = blur(v_texCoord); //* v_fragmentColor.rgb;
  17. gl_FragColor = vec4(col) * v_fragmentColor;
  18. }
  19.  
  20. vec4 blur(vec2 p)
  21. {
  22. if (blurRadius > 0.0 && sampleNum > 1.0)
  23. {
  24. vec4 col = vec4(0);
  25. vec2 unit = 1.0 / resolution.xy;//單位座標
  26.  
  27. float r = blurRadius;
  28. float sampleStep = r / sampleNum;
  29.  
  30. float count = 0.0;
  31. //遍歷一個矩形,當前的座標爲中心點,遍歷矩形中每個像素點的顏色
  32. for(float x = -r; x < r; x += sampleStep)
  33. {
  34. for(float y = -r; y < r; y += sampleStep)
  35. {
  36. float weight = (r - abs(x)) * (r - abs(y));//權重,p點的權重最高,向四周依次減少
  37. col += texture2D(CC_Texture0,p + vec2(x * unit.x,y * unit.y)) * weight;
  38. count += weight;
  39. }
  40. }
  41. //得到實際模糊顏色的值
  42. return col / count;
  43. }
  44.  
  45. return texture2D(CC_Texture0,p);
  46. }

精度限定符和varying變量等的一些基礎的知識在前面的博客中遇到的已經說過。 
uniform變量是頂點着色器和片段着色器共享使用的變量,uniform的值不能被改變。 
uniform變量是由宿主程序設置的,代碼如下:


 
  1. void EffectBlur::setTarget(EffectSprite *sprite)
  2. {
  3. Size size = sprite->getTexture()->getContentSizeInPixels();
  4. _glprogramstate->setUniformVec2("resolution",size);
  5. #if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
  6. _glprogramstate->setUniformFloat("blurRadius",_blurRadius);
  7. _glprogramstate->setUniformFloat("sampleNum",_blurSampleNum);
  8. #endif
  9. }

這裏宿主程序設置了resolutionblurRadiussampleNum三個uniform變量。渲染的時候,頂點着色器和片段着色器都可以用到這三個變量的值。 
resolution是當前渲染node的實際分辨率。 
blurRadius是像素點模糊處理的參考矩形的半徑 
sampleNum選擇像素點的間隔的數量,相鄰像素點的間距等於blurRadius / sampleNum

blur函數就是計算該像素點的最終顏色,參數p是當前像素點的座標,我們以p點爲中點以2r爲邊長得到一個矩形,這個矩形中每隔sampleStep長度的像素點是當前像素點的顏色參考像素。每個像素點會乘以一個weight權重,這個weight越靠近p點值越高,目的是爲了讓最終的值更接近於p點的像素顏色,然後各個像素點乘以權重後的顏色加起來,得到col,把各個權重也加起來得到count。最終的顏色值就是col/count

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章