昨天介紹了畫圓與一些調整的方法
今天除了畫方形外,
也介紹 Shader 裡一個常用的函式:smoothstep()
smoothstep() 的用途是將一個值平滑漸變到另一個值,
公式圖畫起來是這樣:
本文約略介紹 smoothstep() 的結果與用法,詳細數學公式較為生硬,
可參考 官方文件 或 The Book of Shaders: smoothstep 的說明與介紹
實際將 uv.x 用 smoothstep() 做漸變時的效果:
float c = smoothstep(0.4, 0.5, uv.x);
fragColor = vec4(vec3(c),1.0);
範圍從 0.4 到 0.5,漸變的值為 uv.x
將 smoothstep 套在先前畫的圓上:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy;
uv -= .5;
uv.x *= (iResolution.x / iResolution.y);
float d = length(uv);
float r = 0.3;
float c = smoothstep(r, r-0.1, d);
fragColor = vec4(vec3(c),1.0);
}
主要差異為這三行:
float d = length(uv);
float r = 0.3;
float c = smoothstep(r, r-0.1, d);
這個範例裡,定義了半徑是 0.3, smoothstep() 漸變的範圍是 0.3 ~ 0.2
畫出來的就是有漸變的圓了
與畫圓形的方法類似,也是使用 smoothstep()
有兩個比較特別的部分:
step1 * step2
的值,這個部分很有趣,主要有差異的程式碼:
float Band(float t, float start, float end, float blur)
{
float step1 = smoothstep(start-blur, start+blur, t);
float step2 = smoothstep(end+blur, end-blur, t);
return step1 * step2;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord/iResolution.xy;
uv -= .5;
uv.x *= (iResolution.x / iResolution.y);
float c = Band(uv.x, -.2, .2, .01);
fragColor = vec4(vec3(c),1.0);
}
與畫帶子類似,定義了一個叫做 Rect 的方法,執行時呼叫兩次畫帶子的方法,
回傳運算的結果 (float)
float Rect(vec2 uv, float left, float right, float bottom, float top, float blur)
{
float band1 = Band(uv.x, left, right, blur);
float band2 = Band(uv.y, bottom, top, blur);
return band1 * band2;
}
float c = Rect(uv, -.2, .2, -.3, .3, .01);
回傳了 band1 * band2
的值,這個部分與畫帶子時相同
會在明天的內容討論
由於可以控制畫圖的參數,於是可以自己做 displacement filter 效果
示意 Demo 分上下兩區對照,畫面因拖拉互動畫出白色漸層的效果範圍
並將效果再套上原圖產生 displacement filter 的效果
後面的文章會介紹手刻 displacement filter 的方法
包含原理與實作方式 (使用 PixiJS)
本篇參考自
ShaderToy Tutorials Part 1 ~ Part4
系列教學對於學習 Shader 很有幫助,
學習後也較容易延伸思考出自己想要的效果