Shader特效——“Median Filter效果”的实现 【GLSL】
发表于2018-02-07
效果图:
GLSL代码与算法注释:
#define SORT_SIZE 8 float sort[SORT_SIZE]; float medians[SORT_SIZE]; // [0., 1.] -> [0, 255] float quant(float x) { x = clamp(x, 0., 1.); return floor(x * 255.); } float pack(vec3 c) { float lum = (c.x + c.y + c.z) * (1. / 3.); return lum; } vec3 unpack(float x) { return vec3(x); } #define SWAP(a,b) { float t = sort[a]; sort[a] = sort[b]; sort[b] = t; } void bubble_sort(int num)// 简单的冒泡排序 { // 把最小值移到最左边 for(int j = 0; j < num; ++j) { for(int i= num-1; i >j; --i) { if(sort[i] < sort[i-1]) { SWAP(i, i-1); } } } } uniform sampler2D iChannel0; const vec2 iResolution = vec2(512., 512.); void main() { vec2 ooRes = vec2(1.) / iResolution.xy; //SORT_SIZE个列 for (int j=0; j<SORT_SIZE; j++) { //SORT_SIZE个行 for (int i=0; i<SORT_SIZE; i++) { vec2 uv = (gl_FragCoord.xy + vec2(i,j)-vec2(SORT_SIZE/2)) * ooRes; float c = pack( texture2D(iChannel0,uv).rgb ); sort[i] = c; } // 针对某列进行纵向排序 bubble_sort( SORT_SIZE); //保存该列的中值 float m = sort[(SORT_SIZE/2)]; medians[j] = m; } for (int i=0; i<SORT_SIZE; i++) { sort[i] = medians[i]; } //对上一步 SORT_SIZE个列中值 进行横向排序 bubble_sort( SORT_SIZE); // 提取中值 gl_FragColor = vec4(unpack(sort[SORT_SIZE/2]),1.0); }