第 41 课:Radial Shutter Animation
我的解:使用两个不同频率的 cos() 控制遮罩与切图节奏,导致不同步;
我的解
uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
const float PI = 3.141592653589;
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
vec2 ratio = vec2(iResolution.x/iResolution.y,1.0);
vec2 vector = uv*ratio - vec2(0.5)*ratio;
vec4 color = texture(iChannel0, uv);
vec4 color2 = texture(iChannel1, uv);
vec4 black = vec4(0.0,0.0,0.0,1.0);
float frame = cos(0.5*iTime)*0.5 + 0.5;
float frame2 = cos(iTime*1.0)*0.5 + 0.5;
float radians = 1.0 - step(frame2, length(vector));
gl_FragColor = mix(black, mix(color2, color, step(0.5, frame)), radians);
}
复盘笔记
- 使用两个不同频率的
cos()控制遮罩与切图节奏,导致不同步; - 遮罩逻辑:
1.0 - step(frame2, length(vector)); - 切图逻辑:
step(0.5, frame); - 动画进展感知不对称,视觉上“进入快、退出慢”。
- 别人版本的特点
- 遮罩用
sin(iTime + π/2)控制,等效于cos(iTime),实现平滑收缩与展开; - 使用
distance(...) - radius判断遮罩; - 精准切图逻辑:
mod(floor((iTime + π) / (2π)), 2),保证在遮罩最小时(即黑屏瞬间)换贴图; - 遮罩略显绕远,但结构上合理且有效。
- ✅ 合并修正版的提升(你总结后的版本)
- 遮罩用
cos(iTime)控制,2π秒一循环; radius = maxRadius * progress实现动画半径;- 遮罩判断逻辑优化为更简洁直观的
1.0 - step(radius, dist); - 宽高比适配通过
offset = (uv - 0.5) * ratio实现,遮罩在任何屏幕上保持圆形; - 切图仍采用
+π相位偏移,在遮罩最小时切图,完美避开视觉跳变。 - 合并修正版