今天我們一起來做一個三原色的旋轉,為了更好的體現效果呢,我沒有使用圖片作為背景,閒言少敘,我們直接看效果。
圖中就是我們要實現的效果,有紅藍綠三種顏色的圓圈在旋轉,我們需要解決的主要問題有如何使用webgl來畫一個模糊的圓圈,如何使三個圓圈繞一點旋轉。
同時如果你喜歡的話還可以自己做一個延伸,例如時刻更改旋轉的中心等等,這樣效果會更佳的豐富,我在這裡呢就不做延伸了。
基礎的構建我在這裡就不在贅述了,你可以看一下我的另一篇基礎構建的文章,在此我們直接進入最核心的webgl的片元著色器程式碼。
一 webgl畫出一個圓圈
precision mediump float;
varying vec2 uv;
uniform float time;
void main(){
vec3 color;
float blur = 15.0;
color.b = 1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;
gl_FragColor = vec4(color, 1.0 );
}
複製程式碼
我們使用上面的程式碼就輕鬆的構建出了一個圓,接下來我們就看一下這個輕鬆畫出圓的原理。
首先我們定義了一個vec3型別的變數,這個變數的作用就是用來儲存我們改變以後的色值的。
接著我們定義了一個float型別的blur變數,此變數的作用是用來控制畫出圓的模糊距離。
color.b = 1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;
複製程式碼
這句程式碼是畫出圓的關鍵點,我們使用具體的座標事例來說明。
圖中的座標系中我們定義了我們想要畫圓的點A(0.5,0.8),其座標你可以在上面的公式找到。
我們分別將W,X,U點帶入公式看一下。
pow函式是平方函式,pow(x,y)會返回x的y次方。
W => 1.0-(pow(0.5 - 0.5, 2.0) + pow(0.77 - 0.8, 2.0))*15.0 => 0.865
X => 1.0-(pow(0.5 - 0.5, 2.0) + pow(0.4 - 0.8, 2.0))*15.0 => -1.4
U => 1.0-(pow(0.1 - 0.5, 2.0) + pow(0.1 - 0.8, 2.0))*15.0 => -8.75
我們在整個二維平面上面,距離A點越遠的點最後計算出來的值就越大。
在webgl中rgba的取值範圍是在0.0~1.0。
二 畫出三色圓
一個圓的畫法我們已經知道了,那麼我們畫出來三個圓。
precision mediump float;
varying vec2 uv;
uniform float time;
void main(){
vec3 color;
float blur = 15.0;
color.r = 1.0 - (pow(uv.x - 0.24,2.0) + pow(uv.y - 0.35,2.0))*blur;
color.g = 1.0 - (pow(uv.x - 0.75,2.0) + pow(uv.y - 0.35,2.0))*blur;
color.b = 1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;
gl_FragColor = vec4(color, 1.0 );
}
複製程式碼
上面我們使用和畫藍色圓同樣的方式畫出了三色圓,那麼接下來就是讓三色圓進行轉動了。
三 轉動三色圓
precision mediump float;
varying vec2 uv;
uniform float time;
void main(){
vec3 color;
float blur = 15.0;
vec2 rotateCenter = vec2(0.5, 0.5);
vec2 circleA = vec2(rotateCenter.x + 0.3*cos(radians(90.0+time)), rotateCenter.y + 0.3*sin(radians(90.0+time)));
vec2 circleB = vec2(rotateCenter.x + 0.3*cos(radians(210.0+time)), rotateCenter.y + 0.3*sin(radians(210.0+time)));
vec2 circleC = vec2(rotateCenter.x + 0.3*cos(radians(-30.0+time)), rotateCenter.y + 0.3*sin(radians(-30.0+time)));
color.r = 1.0 - (pow(uv.x - circleB.x,2.0) + pow(uv.y - circleB.y,2.0))*blur;
color.g = 1.0 - (pow(uv.x - circleC.x,2.0) + pow(uv.y - circleC.y,2.0))*blur;
color.b = 1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.y,2.0))*blur;
gl_FragColor = vec4(color, 1.0 );
}
複製程式碼
我們首先定義三色圓的旋轉中心,我定義的是rotateCenter(0.5,0.5),接下來我們要將三色圓的圓心和這個點關聯起來。
上面圖中A點是藍色圓的圓心,B點是紅色圓的圓心,C點是綠色圓的圓心,O點是圓的圓心,同時也是三角形的中心。
我們可以根據初高中的知識知道: A(x1,y1),o(x0,y0)
x1 = x0 + r*cos(degrees*PI/180)
y1 = y0 + r*sin(degrees*PI/180)
vec2(rotateCenter.x + 0.3*cos(radians(90.0)), rotateCenter.y + 0.3*sin(radians(90.0)))
複製程式碼
在程式碼中rotateCenter.x就是x0
rotateCenter.y就是y0
0.3就是r也就是圓的半徑
degrees*PI/180我們使用webgl的內建三角函式radians(90.0)進行計算,其中90.0就是A點相對於O點的角度。
這樣我們就將ABC三個點和O點關聯上了,此時只要我們再時時的改變ABC三點相對於O點的角度值,這樣就可以達到旋轉的效果了。
vec2 circleA = vec2(rotateCenter.x + 0.3*cos(radians(90.0+time)), rotateCenter.y + 0.3*sin(radians(90.0+time)));
複製程式碼
在上面我們在radians(90.0+time)的引數中新增了一個變數time,這個time會從0開始一直加1,這樣ABC三個點就會時時的改變相對於O點的角度,進而完成旋轉。
color.b = 1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.y,2.0))*blur;
複製程式碼
最後我們將時時旋轉的三色圓中心座標傳給顏色畫圓的計算公式,這樣就完成了。
旋轉的方式你可以自己手動的更改,並且畫圓那裡使用2次方還是1次方你都可以進行更改,你會得到不一樣的效果,篇幅的原因我就不一個個舉例子了。
color.b = 1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.x,2.0))*blur;
複製程式碼
嗯,怕你感覺對實現的效果失望,你只需要將color.b那裡的旋轉中新都設定成x就會出現上面的效果,更多的效果你可以自己嘗試一下。
最後附上程式碼地址:gitee.com/wangtao_it_…
此次的程式碼是專案下面的rotateRGB.html