Shader特效——實現“抗鋸齒的黑白格”並原理解析【GLSL】
阿新 • • 發佈:2019-01-23
最終效果圖:
完整 程式碼與分析 如下:
#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) 的效果圖為: