Shader特效——“馬賽克”的實現【GLSL】
阿新 • • 發佈:2018-11-08
參考自: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;
}
另附其他效果: