Shader特效——“旋轉粒子”的實現【GLSL】
阿新 • • 發佈:2019-02-01
效果圖:
GLSL程式碼及演算法解釋:
// 動畫相關引數 float dotSize = 0.01; float iteration = 100.; float xAmp = 0.3; float yAmp = 0.1; float speed = 0.05; float rotateCanvas = 0.; float rotateParticles = 1.; float rotateMultiplier = 10.; vec2 pos = vec2(.5, .5); float xFactor = 0.2; float yFactor = 0.2; #define RENDERSIZE vec2(512., 512.) uniform float iGlobalTime; //rotation vec2 rot(vec2 uv, float a) { // [uv.x uv.y] * [cos(a), sin(a), // -sin(a), cos(a)] return vec2(uv.x * cos(a) - uv.y * sin(a), uv.y * cos(a) + uv.x * sin(a)); } float circle(vec2 uv, float size) { // 向量長度在範圍內為白色,範圍外為黑 return length(uv) > size ? 0.0 : 1.0; } void main() { vec2 uv = gl_FragCoord.xy / RENDERSIZE; // [0., 1.] uv -= vec2(pos);// [-.5, .5] uv.x *= RENDERSIZE.x / RENDERSIZE.y; // ratio = X/Y vec3 color = vec3(0); //第一個粒子(i == 0)的 uv【其實第一個粒子是看不見的,因為size == 0】 uv = rot(uv, rotateCanvas); // 99個粒子 for (float i = 0.0; i < 100.0; i++) { // set max number of iterations if (iteration < i) break; // x:sin() y:cos() 的旋轉動畫 vec2 new_pos = vec2(cos(i * xFactor * (iGlobalTime * speed)) * xAmp, sin(i * yFactor * (iGlobalTime * speed)) * yAmp); // st:新位置到uv的向量 vec2 st = uv - new_pos; // 計算st向量的長度,並設定粒子的尺寸(從小到大) float dots = circle((st), dotSize * (i * 0.01)); //旋轉當前粒子的uv得到下一個粒子的uv uv = rot(uv, rotateParticles * rotateMultiplier); // 更新紋素的顏色(只要當前紋素屬於其中一個粒子,則置為白色,否則仍然是黑色) // 嚴謹的話是應該clamp,但是超過1也是白色 color += dots; } gl_FragColor = vec4(vec3(color), 1.0); }