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

版权声明:涉猎过的知识都像是不断汇入大海的涓涓细流,你怎么知道是哪条汇入的溪流让海洋成为海洋呢【转载请注明出处】 https://blog.csdn.net/panda1234lee/article/details/52155653

参考自: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;

}


另附其他效果:





























猜你喜欢

转载自blog.csdn.net/panda1234lee/article/details/52155653