Shader特效——“马赛克”的实现【GLSL】

来源:互联网 发布:怎么使用java 编辑:程序博客网 时间:2024/05/01 23:39

参考自:http://tech.it168.com/n/2007-03-29/200703291522292_3.shtml 和 http://blog.csdn.net/simpledrunk/article/details/17170965


原图:



”圆形” 效果图1 :


“圆形”效果2:



片元着色器代码:

uniform sampler2D Texture0;const vec2 texSize = vec2(640., 640.);const vec2 mosaicSize = vec2(8., 8.);varying vec2 vUV;void main(void){   vec2 xy = vec2(vUV.x * texSize.x, vUV.y * texSize.y);// 取值范围换算到图像尺寸大小   // 计算某一个小mosaic的中心坐标   vec2 xyMosaic = vec2(floor(xy.x / mosaicSize.x) * mosaicSize.x,          floor(xy.y / mosaicSize.y) * mosaicSize.y )         + .5*mosaicSize;   // 计算距离中心的长度         vec2 delXY = xyMosaic - xy;   float delL = length(delXY);   // 换算回纹理坐标系   vec2 uvMosaic = vec2(xyMosaic.x / texSize.x, xyMosaic.y / texSize.y);      vec4 finalColor;   if(delL<0.5*mosaicSize.x)   {      finalColor = texture2D(Texture0, uvMosaic);   }   else   {      //finalColor = texture2D(Texture0, vUV);      finalColor = vec4(0., 0., 0., 1.);   }      gl_FragColor = finalColor;}


“方形” 效果图:



片元着色器代码:

uniform sampler2D Texture0;const vec2 texSize = vec2(640., 640.);const vec2 mosaicSize = vec2(8., 8.);varying vec2 vUV;void main(void){   vec4 color;   //float ratio = texSize.y/texSize.x;      vec2 xy = vec2(vUV.x * texSize.x /** ratio */, vUV.y * texSize.y);      vec2 xyMosaic = vec2(floor(xy.x / mosaicSize.x) * mosaicSize.x,          floor(xy.y / mosaicSize.y) * mosaicSize.y );      //第几块mosaic   vec2 xyFloor = vec2(floor(mod(xy.x, mosaicSize.x)),                   floor(mod(xy.y, mosaicSize.y)));   #if 0   if((xyFloor.x == 0 || xyFloor.y == 0))   {      color = vec4(1., 1., 1., 1.);   }   else   #endif   {      vec2 uvMosaic = vec2(xyMosaic.x / texSize.x, xyMosaic.y / texSize.y);      color = texture2D( Texture0, uvMosaic );   }      gl_FragColor = color;}


“六边形” 效果图:



片元着色器代码:

uniform float Time_x;uniform sampler2D Texture0;varying vec2 vUV;uniform float len;void main (void){   float TR = 0.866025;   float x = vUV.x;   float y = vUV.y;   int wx = int(x/1.5/len);   int wy = int(y/TR/len);   vec2 v1, v2, vn;   if(wx/2 * 2 == wx) {      if(wy/2 * 2 == wy) {            v1 = vec2(len*1.5*wx, len*TR*wy);            v2 = vec2(len*1.5*(wx+1), len*TR*(wy+1));         } else {            v1 = vec2(len*1.5*wx, len*TR*(wy+1));            v2 = vec2(len*1.5*(wx+1), len*TR*wy);         }      } else {      if(wy/2 * 2 == wy) {         v1 = vec2(len*1.5*wx, len*TR*(wy+1));         v2 = vec2(len*1.5*(wx+1), len*TR*wy);         } else {            v1 = vec2(len*1.5*wx, len*TR*wy);            v2 = vec2(len*1.5*(wx+1), len*TR*(wy+1));         }   }   float s1 = sqrt( pow(v1.x-x, 2) + pow(v1.y-y, 2) );   float s2 = sqrt( pow(v2.x-x, 2) + pow(v2.y-y, 2) );   if(s1 < s2)      vn = v1;   else      vn = v2;   vec4  color = texture2D(Texture0, vn);   gl_FragColor = color;}


“三角形” 效果图:



片元着色器代码:

varying vec2 vUV;uniform sampler2D Texture0;// len 是六边形的边长uniform float len;void main (void){   const float TR = 0.866025;  // .5*(3)^.5   const float PI6 = 0.523599; // PI/6      float x = vUV.x;   float y = vUV.y;      // 1.5*len 是矩形矩阵的长,TR*len 是宽   // ::计算矩形矩阵的顶点坐标 (0,0)(0,1)(1,0)(1,1)   int wx = int(x/(1.5*len));   int wy = int(y/(TR*len));      vec2 v1, v2, vn;      // 判断是矩形的哪个顶点,上半部还是下半部   if(wx/2 * 2. == wx)    {      if(wy/2 * 2. == wy)       {     // left top            // 选择位于六边形中心的纹素作为颜色参考:左上右下            v1 = vec2(len*1.5*wx, len*TR*wy);            v2 = vec2(len*1.5*(wx+1), len*TR*(wy+1));      }       else       {  // left bottom         // 左下右上         v1 = vec2(len*1.5*wx, len*TR*(wy+1));         v2 = vec2(len*1.5*(wx+1), len*TR*wy);      }   }    else    {      if(wy/2 * 2. == wy)       {  // right top         // 左下右上         v1 = vec2(len*1.5*wx, len*TR*(wy+1));         v2 = vec2(len*1.5*(wx+1), len*TR*wy);      }       else       {  // right bottom         // 左上右下         v1 = vec2(len*1.5*wx, len*TR*wy);         v2 = vec2(len*1.5*(wx+1), len*TR*(wy+1));      }   }   // 计算参考点与当前纹素的距离   float s1 = sqrt( pow(v1.x-x, 2.) + pow(v1.y-y, 2.) );   float s2 = sqrt( pow(v2.x-x, 2.) + pow(v2.y-y, 2.) );   // 选择距离小的参考点   if(s1 < s2)      vn = v1;   else      vn = v2;         vec4 mid = texture2D(Texture0, vn);   float a = atan((x-vn.x)/(y-vn.y));// 计算夹角   // 分别计算六个三角形的中心点坐标,之后将作为参考点   vec2 area1 = vec2(vn.x, vn.y-len*TR/2.);   vec2 area2 = vec2(vn.x+len/2., vn.y-len*TR/2.);   vec2 area3 = vec2(vn.x+len/2., vn.y+len*TR/2.);   vec2 area4 = vec2(vn.x, vn.y+len*TR/2.);   vec2 area5 = vec2(vn.x-len/2., vn.y+len*TR/2.);   vec2 area6 = vec2(vn.x-len/2., vn.y-len*TR/2.);      // 根据夹角判断是哪个三角形   if(a >= PI6 && a < PI6*3.)      vn = area1;   else if(a>=PI6*3. && a<PI6*5.)      vn = area2;   else if((a>=PI6*5. && a<=PI6*6.) || (a<-PI6*5. && a>-PI6*6.))      vn = area3;   else if(a<-PI6*3. && a>=-PI6*5.)      vn = area4;   else if(a<=-PI6 && a>-PI6*3.)      vn = area5;   else if(a>-PI6 && a<PI6)      vn = area6;         vec4  color = texture2D(Texture0, vn);   gl_FragColor = color;}


另附其他效果:





























0 0