跳到主要内容
← Built-In functions

Built-In functions

Radial Shutter Animation

使用两个不同频率的 `cos()` 控制遮罩与切图节奏,导致不同步;

实时渲染 · 纹理 GLSL

第 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 实现,遮罩在任何屏幕上保持圆形;
  • 切图仍采用 +π 相位偏移,在遮罩最小时切图,完美避开视觉跳变。
  • 合并修正版