上色沒什麼問題的話,那來畫圖吧!
可是
fragment shader 沒有像是 drawRect()
、drawCircle()
的方法
先前提到的,用數學方式畫出想要的畫面
畫圈呢?
圓是從圓心到邊界距離固定的形狀,
也就是定義好圓心與半徑後,就能畫出圓了
float d = length(uv);
vec3 col = vec3(d);
在這邊用了 length() 公式:
length Vector length.
float length (gentype p)
Description
Returns the length of vector p, i.e., the square root of (p.x2 + p.y2 + ...)
從公式來推:
length(0., 0.) 結果是 0
length(0., 1.) 結果是 1
length(1., 1.) 結果是 √2
,大於1,顯示為白色
length(1., 0.) 結果是 1
因此畫出來的圖是黑到白, 1/4 的...橢圓形
由於 WebGL 是由 Khronos Group 維護,
我在查找 API 時會到 khronos 的 文件查找
length()
四個角落的 length() 值算出來是 0
~ 1
,
但由於畫面本身不是正方形
因此畫出來的形狀是橢圓形
將橢圓形乘上邊界比,就是正圓了
uv.x *= iResolution.x /iResolution.y;
float d = length(uv);
vec3 col = vec3(d);
相當單純,將 uv 的值各 減去 .5
即可
uv -= .5; // -.5 ~ // .5
uv.x *= iResolution.x /iResolution.y;
float d = length(uv);
vec3 col = vec3(d);
需留意的是,需要先調整中心位置,然後再調整變形
如果兩行程式碼調換
就會變成形狀正確,但位置並沒有置中的情形
uv.x *= iResolution.x /iResolution.y;
uv -= .5;
float d = length(uv);
vec3 col = vec3(d);
用單純的判斷式即可,當 length() 的結果 大於 .3 時
顯示為白色,反之為黑色
uv -= .5; // -.5 ~ // .5
uv.x *= iResolution.x /iResolution.y;
float d = length(uv);
float c = d;
if(d>.3)c=1.;else c=0.;
vec3 col = vec3(c);
用畫的很麻煩,如果要取得一樣的結果
把圖片當做素材讀入使用也是一種做法
讀圖片會有檔案大小、解析度、吃效能的問題
但可能相較容易維護
本篇參考自 Shadertoy for absolute beginners,
系列教學對於學習 Shader 很有幫助,
學習後也較容易延伸思考出自己想要的效果