1. 程式人生 > >Shader特效——實現“抗鋸齒的黑白格”並原理解析【GLSL】

Shader特效——實現“抗鋸齒的黑白格”並原理解析【GLSL】

最終效果圖:


完整 程式碼與分析 如下:

#extension GL_OES_standard_derivatives:enable

//precision highp float;

uniform int     u_frequency; // ❤ 小格子的個數 = (2*freq)^2, 大格子的個數 = freq^2
uniform vec4    u_color0;    // 白色
uniform vec4    u_color1;    // 黑色

varying vec2    v_st;

void
main()
{
   vec4   color;
   vec2   st_width;
   vec2   fuzz;
   vec2   pmod;
   float  fuzz_max;
   
   st_width = fwidth(v_st);
   fuzz = st_width * float(u_frequency) * 2.0; 
   fuzz_max = max(fuzz.s, fuzz.t);
   pmod = fract(v_st * float(u_frequency));      // ❤ 建立大網格,每個格子的 pmod 都 ∈ [0, 1)
   
   // 測試
   //color = vec4(v_st * float(u_frequency), 0., 1.);
   //color = vec4(pmod, 0., 1.);                 // 測試pmod
   //color = vec4(fwidth(pmod).x, 0., 0., 1.);   // 測試fwidth
   //color = vec4(fwidth(pmod).y, 0., 0., 1.);
   //color = vec4(abs(dFdx(pmod).x), 0., 0., 1.);// 測試dFdx
   //color = vec4(abs(dFdy(pmod).y), 0., 0., 1.);// 測試dFdy
   
   if (fuzz_max <= 0.5)
   {
      // smoothstep 在模糊區間上進行插值,分界線的寬度為fuzz
      // ❤ 建立更多格子,將原來的大格均分為四
      vec2  p = smoothstep(vec2(0.5), fuzz + vec2(0.5), pmod)   // 大部分的格子,並控制格子的比例
               +(1.0 - smoothstep(vec2(0.0), fuzz, pmod));      // 一部分的邊界
      // TEST
      //color = vec4(p, 0., 1.);
      
      color = mix(u_color0, u_color1, p.x * p.y + (1.0 - p.x) * (1.0 - p.y));            // 顏色混合:非黑即白
      //color = mix(color, (u_color0 + u_color1)/2.0, smoothstep(0.125, 0.5, fuzz_max)); // 和灰色混合, 但效果不明顯
   }
   else
   {
      color = (u_color0 + u_color1)/2.0;;
   }
   
   gl_FragColor = color;
}

測試圖:

1. pmod 的測試結果


2. fwidth(pmod).x 和 abs(dFdx(pmod).x) 的效果【即 fwidth 的x分量和 dFdx 的x分量的絕對值相等】

3. fwidth(pmod).y 和 abs(dFdy(pmod).y) 的效果 【即 fwidth 的y分量和 dFdy 的y分量的絕對值相等】


可得出結論:fwidth(pmod).xy == vec2(abs(dFdx(pmod).x) , abs(dFdy(pmod).y))

 注:dFdx dFdy的意義

http://stackoverflow.com/questions/16365385/explanation-of-dfdx

http://stackoverflow.com/questions/28246413/understanding-the-basics-of-dfdx-and-dfdy


4. p 的效果



函式圖:

1. smoothstep(vec2(0.5), fuzz + vec2(0.5), pmod) 的效果圖為:


2. 1.0 - smoothstep(vec2(0.0), fuzz, pmod 的效果圖為:


3. smoothstep(vec2(0.5), fuzz + vec2(0.5) + 1.0 - smoothstep(vec2(0.0), fuzz, pmod 的效果圖為:


4. p.x * p.y + (1.0 - p.x) * (1.0 - p.y) 的效果圖為: