Shader特效——實現“放大鏡/縮小鏡”【GLSL】
阿新 • • 發佈:2019-01-28
放大效果:
縮小效果:
片元著色器程式碼:
const float in_circle_radius = 96.; //從客戶端傳入的放大鏡圓半徑 const float in_zoom_times = 2.; //從客戶端傳入的放大鏡放大倍數 const float imageWidth = 640.; //從客戶端傳入的圖片寬資料 const float imageHeight = 640.; //從客戶端傳入的圖片高資料 uniform sampler2D Texture0; varying vec2 vUV; vec2 in_circle_pos = vec2(320., imageHeight-320.); //從客戶端傳入的放大鏡圓心位置 // 轉換為紋理範圍 vec2 transForTexPosition(vec2 pos) { return vec2(float(pos.x/imageWidth), float(pos.y/imageHeight)); } // Distance of Points float getDistance(vec2 pos_src, vec2 pos_dist) { float quadratic_sum = pow((pos_src.x - pos_dist.x), 2.) + pow((pos_src.y - pos_dist.y), 2.); return sqrt(quadratic_sum); } vec2 getZoomPosition() { // zoom_times>1. 是放大, 0.< zoom_times <1.是縮小 float zoom_x = float(gl_FragCoord.x-in_circle_pos.x) / in_zoom_times; float zoom_y = float(gl_FragCoord.y-in_circle_pos.y) / in_zoom_times; return vec2(float(in_circle_pos.x + zoom_x), float(-in_circle_pos.y + zoom_y)); } vec4 getColor() { // ❤ vec2 pos = getZoomPosition(); float _x = floor(pos.x); float _y = floor(pos.y); float u = pos.x - _x; float v = pos.y - _y; //雙線性插值取樣 vec4 data_00 = texture2D(Texture0, transForTexPosition(vec2(_x, _y))); vec4 data_01 = texture2D(Texture0, transForTexPosition(vec2(_x, _y + 1.))); vec4 data_10 = texture2D(Texture0, transForTexPosition(vec2(_x + 1., _y))); vec4 data_11 = texture2D(Texture0, transForTexPosition(vec2(_x + 1., _y + 1.))); return (1. - u) * (1. - v) * data_00 + (1. - u) * v * data_01 + u * (1. - v) * data_10 + u * v * data_11; } void main(void) { vec2 frag_pos = vec2(gl_FragCoord.x, gl_FragCoord.y); //若當前片段位置距放大鏡圓心距離大於圓半徑時,直接從紋理中取樣輸出片段顏色 if (getDistance(in_circle_pos, frag_pos) > in_circle_radius) gl_FragColor = texture2D(Texture0, vUV); else //距離小於半徑的片段,二次線性插值獲得顔色。 gl_FragColor = getColor(); }