Shader 動畫

Shader 動畫和 Canvas 動畫原理是同樣的,經過定時器循環渲染,並改變畫布中圖形的屬性來實現動畫。html

一些 Shader 編輯器都已經實現好了定時器的功能,同時會傳遞一些跟時間相關的值給到着色器代碼中,如 ShaderToy 中與時間相關的屬性是 iTime/iTimeDelta,gl-transition 中與時間相關的屬性是 progress。經過將着色器代碼中的變量與時間相結合,就可讓動畫產生。git

1、位移動畫

在以前的文章中講到了座標的運算,其中加減就是位移:github

那常規的位移動畫就不說,下面講些複雜的運動:app

1. 圓周運動

st += vec(cos(u_time), sin(u_time)) 就是圓周運動了:編輯器

2、旋轉

旋轉能夠經過矩陣來輕鬆完成:函數

但你會發現,當咱們把矩陣和座標相乘,獲得的確實上面的圓周運動,這是由於旋轉座標在左下角,若是想旋轉矩形,則必須把中心點挪到矩形中心,或者換個說法,把矩形中心挪到左下角。post

封裝好的代碼:動畫

mat2 rotate2d(float _angle){
    return mat2(cos(_angle),-sin(_angle),
                sin(_angle),cos(_angle));
}
複製代碼

當咱們在非正方形的畫布中對材質進行旋轉的時候,會遇到一個難以避開的問題,就是拉伸問題。舉個例子,當畫布是矩形時,暴露了旋轉時拉伸的問題:ui

// 部分代碼
void main() {
    vec2 st = textureCoordinate;
    float ratio = inputImageTextureSize.x / inputImageTextureSize.y;
    float animationTime = getAnimationTime();
    float easingTime = animationTime;

    float bigRotation = 30./180.*3.14159;
    st = rotateUv(st, bigRotation*easingTime, vec2(.5, .5), 1.);

    gl_FragColor = texture2D(inputImageTexture, st);
}
複製代碼

這篇文章也提到了這個問題,之因此會出現這個問題,是由於因爲寬高的比例不是 1:1,說明雖然 x 和 y 的座標都是 0~1,可是它們表示的長度是不同的,正由於這個長度不同,致使在旋轉的時候,像素點的運動並不符合畫布的比例: spa

而解決方案也比較簡單,咱們在旋轉的時候,對 y 軸進行畫布比例的拉伸便可:

void main() {
    vec2 st = textureCoordinate;
    float ratio = inputImageTextureSize.x / inputImageTextureSize.y;
    float animationTime = getAnimationTime();
    float easingTime = animationTime;

    float bigRotation = 30./180.*3.14159;

    st.y *= 1./ratio;
    st = rotateUv(st, bigRotation*easingTime, vec2(.5, .5), 1.);
    st.y *= ratio;

    gl_FragColor = texture2D(inputImageTexture, st);
}
複製代碼

3、縮放

縮放就是座標的乘除運算,一樣也能夠經過矩形來實現:

同理,若是不對座標系進行轉換,縮放的中心仍是在左下角:

兩個動畫組合一塊兒:

封裝好的代碼:

mat2 scale(vec2 _scale){
    return mat2(_scale.x,0.0,
                0.0,_scale.y);
}
複製代碼

4、正弦運動

正弦餘弦是很是優美的動畫曲線,咱們在講函數可視化也展現過下面這張圖(圖片來源於bookofshader):

因此經過這張圖你應該知道正弦餘弦函數能夠作出什麼樣的效果了,咱們來試試:

這是笛卡爾座標系的運動,假設咱們把座標系變成極座標系,你們能腦補大概的效果了嗎?

假如我想作一個外向擴散的動畫,相似雷達那樣的效果呢?去掉 sin() 函數便可:

相關連接:

相關文章
相關標籤/搜索