咱們能夠經過頂點着色器來繪製點線面圖形,並組合成其餘各類形狀,可是通常 2D 場景中,頂點着色器通常都不改,而且它通常決定的是整個畫布的大小。因此這裏探討的是經過片元着色器來繪製基礎圖形。api
把一切圖形的繪製想象是在一張佈滿格子(像素點)的紙上畫畫: 函數
圓形的繪製須要藉助極座標系,肯定了圓心 c,半徑 r 就能獲得任意的圓形:post
當咱們在笛卡爾座標系裏想要繪製一個圓時候,你會發現很難,由於你沒有辦法將畫布中的每一個像素點跟 center 和 radius 結合:優化
因此這裏須要把笛卡爾座標系轉成極座標系,轉換公式能夠參考下面:ui
因此咱們能夠這麼改:spa
固然你會發現這個圓的邊緣有鋸齒,能夠經過 smoothstep 來優化邊緣問題:3d
假如咱們想繪製一個橢圓呢?code
橢圓能夠理解爲把圓往水平或者垂直方向進行拉伸,正好上一篇講到了座標的計算,經過乘以一個小於 1 的數字,能夠放大:cdn
封裝成函數:blog
float circle(in vec2 _st, in float _radius){
vec2 l = _st-vec2(0.5);
return 1.-smoothstep(_radius-(_radius*0.01),
_radius+(_radius*0.01),
dot(l,l)*4.);
}
複製代碼
矩形繪製能夠理解爲四邊向內縮小,獲得畫布內的矩形:
因此若是想獲得一個非正方形,只須要水平和垂直不公用一個 padding 便可。或者經過上面橢圓的方式把座標和一個係數相乘。
若是繪製平行四邊形呢?若是要繪製平行四邊形,意味着水平或者垂直的間距是傾斜的。這裏就拿水平方向的平行四邊形來講,那兩邊的黑邊要傾斜,腦補下咱們經常使用的 y = ax 線在座標系的呈現,能夠這麼改:
本來咱們只單獨使用 st.x 或 st.y,那麼它們只表明一條垂直 x 或 有軸的直線。而經過st.x + st.y
引入了兩個變量,獲得了一條二元線性方程,並能產生斜邊。之因此*0.3-0.2
是爲了調整傾斜角度和調整傾斜面積。
固然還有更加方便的繪製矩形的方式,兩步便可。只要把每次的單一變量變成雙變量:
封裝成函數:
float box(vec2 _st, vec2 _size, float _smoothEdges){
_size = vec2(0.5)-_size*0.5;
vec2 aa = vec2(_smoothEdges*0.5);
vec2 uv = smoothstep(_size,_size+aa,_st);
uv *= smoothstep(_size,_size+aa,vec2(1.0)-_st);
return uv.x*uv.y;
}
複製代碼
直線其實就是向下或者左右邊距很大,致使中間區域很小所呈現出來的樣子:
想要線多細取決於你的間距設多大。若是是斜線呢?
還有一種更簡單到寫法:
封裝出一個畫線函數:
經過改變指數,能夠創造出不同的曲線:
封裝成函數:
float plot(vec2 st, float pct){
return smoothstep( pct-0.02, pct, st.y) -
smoothstep( pct, pct+0.02, st.y);
}
複製代碼
有了上面傾斜角度的經驗,咱們能夠繼續這麼作:
封裝了繪製多邊形的函數:
float polygon(vec2 _st, int num) {
// Remap the space to -1. to 1.
_st = _st *2.-1.;
// Angle and radius from the current pixel
float a = atan(_st.x, _st.y) + PI;
float r = TWO_PI/float(num);
// Shaping function that modulate the distance
float d = cos(floor(.5+a/r)*r-a) * length(_st);
return 1.0-smoothstep(.4,.41,d);
}
複製代碼
如今都是一個界面只能有一個圖形,假設想要把兩種圖形放在一塊兒,或者把變換過座標系的圖形和沒有變換過座標系的圖形放在一塊兒,應該怎麼作?
咱們先看看沒有變換座標系的:
先畫一個小圓圈:
咱們能夠經過改變圓心位置,並經過像素點加法來進行組合。
同理,對於變動過座標體系的,在什麼時候的時間進行重置,也能夠混合不一樣的體系的圖形在一塊兒:
那其實這樣會破壞掉原來的座標系,咱們能夠優化一下:
顏色的混合能夠用乘法,也能夠用 mix(),咱們在以前的文章裏提過:黑色和任何顏色相乘,都是黑色。白色和任何顏色相乘,都會變成那個顏色。
因此這裏能夠這麼寫: