【Shader特效8】著色器濾鏡、影象卷積與濾波、數字影象處理
##說在開頭: PhotoShop和特效相機中有許多特效的濾鏡。片元著色器時基於片元為單位執行的,完全可以實現特殊的濾鏡效果。要想實現這些濾鏡效果還需要簡單的瞭解《數字影象處理》中的影象卷積與濾波的一些知識,我把所有程式碼都放到了我的github上https://github.com/ModestBean/ShaderSample。本人的知識有限,如果本節內容有錯誤和不合理之處,還請朋友們多多指出,我會虛心接受每一個建議。 #####參考內容:
- 《OpenGL ES 3.X 遊戲開發 下卷》
- zouxy09的部落格:http://blog.csdn.net/zouxy09/article/details/49080029
#version 400 #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable layout (binding = 1) uniform sampler2D sTexture;//紋理取樣器 layout (location = 0) in vec2 vTextureCoord;//紋理座標 layout (location = 0) out vec4 outColor;//輸出片元顏色 void main() { //紋理偏移量單位步進 const float stStep = 512.0; const float scaleFactor = 1.0/9.0;//給出最終求和時的加權因子(為調整亮度) //給出卷積核心中各個元素對應畫素相對於待處理畫素的紋理座標偏移量 vec2 offsets[9]=vec2[9]( vec2(-1.0,-1.0),vec2(0.0,-1.0),vec2(1.0,-1.0), vec2(-1.0,0.0),vec2(0.0,0.0),vec2(1.0,0.0), vec2(-1.0,1.0),vec2(0.0,1.0),vec2(1.0,1.0) ); //卷積核心中各個位置的值 float kernelValues[9]=float[9] ( 1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0 ); //最終的顏色值 vec4 sum=vec4(0,0,0,0); //顏色求和 for(int i=0;i<9;i++){ sum=sum+kernelValues[i]*scaleFactor*texture(sTexture, vTextureCoord+offsets[i]/stStep); } outColor=sum; }
顏色求和部分的程式碼稍微不好理解。 1、首先kernelValues[i]*scaleFactor,scaleFactor為卷積核心中數的和的倒數,也就是1/9,這麼做的目的是為了保持圖片的亮度與原來的亮度不變,這個數大於1時,處理後的圖片變亮,小於1處理後的圖片變暗。 2、然後是texture(sTexture, vTextureCoord+offsets[i]/stStep),這裡讓紋理座標的偏移量除以stStep,stStep為紋理座標偏移量的步進,在著色器中控制著濾波器處理區域的大小。 ###邊緣檢測 #####片元著色器程式碼(EdgeDetection.frag)只給出卷積核心的值
//卷積核心中各個位置的值
float kernelValues[9]=float[9] (
0.0,1.0,0.0,
1.0,-4.0,1.0,
0.0,1.0,0.0
);
###銳化效果 #####片元著色器程式碼(Sharpen.frag)只給出卷積核心的值
float kernelValues[9]=float[9] (
0.0,-1.0,0.0,
-1.0,5.0,-1.0,
0.0,-1.0,0.0
);
###浮雕效果 #####片元著色器程式碼(SmoothFilter.frag)只給出卷積核心的值
float kernelValues[9]=float[9] (
2.0,0.0,2.0,
0.0,0.0,0.0,
3.0,0.0,-6.0
);
###均值模糊 #####片元著色器程式碼(MeanBlur.frag)只給出卷積核心的值 可以多次模糊也是可以的
float kernelValues[9]=float[9] (
0.0,1.0,0.0,
1.0,1.0,1.0,
0.0,1.0,0.0
);
###高斯模糊 #####片元著色器程式碼(GaussianBlur.frag)只給出卷積核心的值
const float scaleFactor = 1.0/209.0;//給出最終求和時的加權因子(為調整亮度)
//卷積核心中各個位置的值
float kernelValues[9]=float[9] (
16.0,26.0,16.0,
26.0,41.0,26.0,
16.0,26.0,16.0
);
這裡的加權因子應該為卷積核心所有值的和的倒數。也就是1/209。 ##數字影象處理中卷積邊界的處理 他的部落格中總結的很好。 ##片元著色器中的邊界處理 對於片元著色器中的邊界處理我還沒有理解清楚,希望清楚的人可以解答。 ##最後 這裡只是簡單的介紹了幾種卷積核心,還有更多的卷積核心,不同的卷積核心實現的效果也不同,我只是把這些知識使用片元著色器實現了,有什麼問題可以互相討論,我的知識水平也有限,有什麼問題希望大家指出。