请教下:做缩放动画时,画面会有抖动的感觉,不流畅,如何解决呢?
https://github.com/user-attachments/assets/a36cb875-6037-4d89-ba32-8f54f5b92140
demo代码如下:
func scaleAnimationDemo() -> VideoLab {
// 1. LayerGroup
var timeRange = CMTimeRange(start: CMTime.zero, duration: CMTime(seconds: 5, preferredTimescale: 600))
let keyTimes = [CMTime(seconds: 0, preferredTimescale: 600),
CMTime(seconds: 5, preferredTimescale: 600)]
let animation1 = KeyframeAnimation(keyPath: "scale",
values: [1, 1.2],
keyTimes: keyTimes,
timingFunctions: [.quadraticEaseInOut])
var transform = Transform.identity
transform.animations = [animation1]
// Add sub-renderLayer1
let image = UIImage(named: "image2.HEIC")
let imageSource = ImageSource(cgImage: image?.cgImage)
imageSource.selectedTimeRange = CMTimeRange(start: CMTime.zero, duration: timeRange.duration)
timeRange = imageSource.selectedTimeRange
let renderLayer1 = RenderLayer(timeRange: timeRange, source: imageSource)
renderLayer1.transform = transform
// 2. Composition
let composition = RenderComposition()
composition.renderSize = CGSize(width: 2016, height: 1512)
composition.layers = [renderLayer1]
// 3. VideoLab
let videoLab = VideoLab(renderComposition: composition)
return videoLab
}
找到原因了:
需要把metal中的 constexpr sampler quadSampler;
修改成
constexpr sampler quadSampler(coord::normalized, address::clamp_to_edge, filter::linear);
具体原因如下:
在 Metal 开发中,constexpr sampler 用于声明常量采样器对象,constexpr sampler quadSampler; 和 constexpr sampler quadSampler(coord::normalized, address::clamp_to_edge, filter::linear); 存在明显区别,下面为你详细分析:
1. constexpr sampler quadSampler;
这行代码声明了一个名为 quadSampler 的常量采样器对象,但没有显式指定其采样参数。在这种情况下,quadSampler 会使用默认的采样参数。
默认参数说明
坐标模式(coord):通常默认是 coord::normalized,表示纹理坐标使用归一化坐标(范围从 0.0 到 1.0)。
寻址模式(address):默认的寻址模式可能是 address::repeat,即当纹理坐标超出 [0, 1] 范围时,纹理会重复采样。
过滤模式(filter):默认过滤模式一般是 filter::nearest,采用最近邻过滤,在采样时会选择离采样点最近的纹理像素值。
2. constexpr sampler quadSampler(coord::normalized, address::clamp_to_edge, filter::linear);
这行代码同样声明了一个名为 quadSampler 的常量采样器对象,不过显式地指定了采样参数。
显式参数说明
坐标模式(coord::normalized):明确指定使用归一化坐标,这意味着纹理坐标范围是从 0.0 到 1.0。如果纹理坐标超出这个范围,会根据寻址模式进行处理。
寻址模式(address::clamp_to_edge):当纹理坐标超出 [0, 1] 范围时,会将坐标值钳制到纹理的边缘。也就是说,如果纹理坐标小于 0.0,会被视为 0.0;如果大于 1.0,会被视为 1.0。这样可以避免纹理重复或出现未定义行为。
过滤模式(filter::linear):使用线性过滤,在采样时会对周围的纹理像素进行加权平均,从而得到更平滑的采样结果。与最近邻过滤相比,线性过滤可以减少锯齿和块状效应,使纹理看起来更加平滑。
总结
constexpr sampler quadSampler; 使用默认的采样参数,适用于对采样效果要求不高,或者希望使用简单默认设置的场景。
constexpr sampler quadSampler(coord::normalized, address::clamp_to_edge, filter::linear); 显式指定了采样参数,能根据具体需求精确控制纹理采样的行为,例如在需要平滑过渡、避免纹理重复等场景中使用。
@yinghuochong 感谢提出的 issue,并且找到了解决方案。如果方便的话,欢迎提一个 Pull request。