导读:本期聚焦于湖南程序员创作的《如何在iOS上用Core Image生成分形云纹理并实现云层厚度控制与动态飘动效果?》,敬请观看详情。云朵纹理的本质是分形噪声:把多个频率递增、振幅递减的噪声信号叠加在一起,就能得到边缘自然、层次丰富的云团形态。iOS系统自带的Core Image框架提供了CIPerlinNoiseGenerator等现成滤镜,配合CIColorControls、CIFilter的参数插值以及CADisplayLink驱动的时间偏移量,无需引入任何第三方库就能在iPhone上实时渲染出可控厚度、可循环飘动的云层效果。本文将从分形布朗运动的数学原理讲起,逐步给出噪声叠加生成云朵纹理的完整代码、控制云层厚度的调参思路,以及让云持续飘移的动画实现方案,并分析各环节的性能优化要点。

在天气类App、游戏场景或动态壁纸中,程序化生成的云朵比静态图片素材更灵活:它不占包体积、可以任意调整形态,还能随时间无限变化。Core Image作为iOS系统级图像处理框架,内置了柏林噪声生成器,配合GPU加速的滤镜链,完全可以在移动端实时渲染出高质量的分形云。本文围绕三个核心问题展开:如何叠加噪声生成分形云纹理、如何通过参数控制云层厚度、如何让云飘起来。

如何在iOS上用Core Image生成分形云纹理并实现云层厚度控制与动态飘动效果?

一、分形噪声的原理与云朵纹理生成

单一频率的柏林噪声看起来只是一团模糊的灰雾,真正的云之所以逼真,是因为大气中的湍流具有跨尺度的自相似性——大尺度决定云的整体轮廓,小尺度填充边缘的絮状细节。这就是分形布朗运动(fBm)的核心思想:将若干个 octave(倍频程)的噪声叠加,每个 octave 的频率翻倍、振幅减半,公式为 noise(p) + 0.5 × noise(2p) + 0.25 × noise(4p) + …。叠加的层数越多,细节越丰富,但计算量也线性增长,移动端通常取4到6层已经足够。

Core Image提供了CIFilter.perlinNoiseGenerator()(旧API为CIPerlinNoiseGenerator),它支持通过inputFrequency、inputOctaves等参数直接生成多倍频噪声,这省去了手动叠加的麻烦。下面是一段Swift代码,生成基础云纹理:

func makeCloudTexture(size: CGSize) -> CIImage? {
    guard let noise = CIFilter(name: "CIPerlinNoiseGenerator") else { return nil }
    // 调整噪声参数
    noise.setValue(0.007, forKey: "inputFrequency")  // 基础频率,越小云团越大
    noise.setValue(6, forKey: "inputOctaves")        // 倍频层数,细节丰富度
    noise.setValue(2.0, forKey: "inputPersistence")  // 持续度,越高细节越明显
    let seed = Int.random(in: 0...1000)
    noise.setValue(NSNumber(value: seed), forKey: "inputSeed")
    guard let output = noise.outputImage else { return nil }
    // 噪声是无边界的,裁剪到目标尺寸
    let center = CGPoint(x: size.width / 2, y: size.height / 2)
    let translated = output.transformed(by: CGAffineTransform(
        translationX: center.x - output.extent.width / 2,
        y: center.y - output.extent.height / 2))
    return translated.cropped(to: CGRect(origin: .zero, size: size))
}

需要注意,噪声生成器输出的灰度图是彩色的偏蓝噪声,云是灰度形态,所以后续还需要做去色处理。如果想要更强烈的自相似效果,也可以手动创建多个不同频率的噪声图再用CIAdditionCompositing合成,但实测系统滤镜的octaves参数已经能覆盖绝大多数场景,手动叠加主要用在需要非均匀衰减系数的场合。

二、云层厚度控制:从灰度映射到密度调节

拿到噪声纹理后,直接显示只是一片灰雾,云的“厚度感”来自于灰度值到形态的映射方式。云越厚,内部越不透光、越白亮,边缘越稀薄。实现上分两步:第一步用CIColorControls提高对比度并去饱和,把中间灰挤压到两端;第二步用CIColorMatrix或自定义kernel做阈值软化,让低于某个灰度的区域变透明,形成轮廓清晰的云团。

func applyCloudDensity(_ input: CIImage, thickness: CGFloat) -> CIImage {
    // 第一步:去色并增强对比,thickness越大对比越强,云团越紧实
    let controls = CIFilter(name: "CIColorControls")!
    controls.setValue(input, forKey: kCIInputImageKey)
    controls.setValue(0.0, forKey: "inputSaturation")           // 完全去色
    controls.setValue(1.0 + thickness * 0.8, forKey: "inputContrast")
    controls.setValue(0.05, forKey: "inputBrightness")
    var result = controls.outputImage!

    // 第二步:用gamma曲线把暗部压成透明,亮部提白
    // 简单做法是再做一次CIColorControls,用brightness反向调整
    let lift = CIFilter(name: "CIGammaAdjust")!
    lift.setValue(result, forKey: kCIInputImageKey)
    lift.setValue(0.6 + (1.0 - thickness) * 0.4, forKey: "inputPower")
    result = lift.outputImage!
    return result
}

thickness参数的实际含义可以这样理解:接近1时,gamma值降低,中低灰度被快速抬升,云团蓬松饱满、覆盖面积大;接近0时gamma接近1,只有噪声峰值处成云,天空显得稀薄晴朗。另外一种更物理化的做法是按高度渐变调整厚度:用CILinearGradient生成从地平线到天顶的蒙版,再与云纹理做CIBlendWithMask合成,得到底部厚顶部薄的层积云效果,这种手法在天气App中很常见。

如果需要体积感更强的云,可以把同一噪声图采样三次偏移不同距离,分别作为R、G、B通道的密度输入,模拟光线在不同深度散射后的色差。成本几乎不变,但立体感提升明显。

三、动态云飘效果的实现与性能优化

让云飘起来最优雅的方式不是移动图片,而是移动噪声的采样坐标。每种动态噪声都有时间维度,但Core Image的柏林噪声生成器本身不含时间轴,惯用做法是在输出图像上叠加一个随时间递增的平移变换,同时对noiseSeed或坐标做周期处理。关键在于保证无缝循环:如果直接平移图像,飘出边界会露馅,正确做法是让噪声纹理尺寸大于显示区域,平移量在一个安全区间内往返,或者生成两倍宽的纹理做滚动裁剪。

class CloudRenderer {
    private var startTime: CFTimeInterval = 0
    private let context = CIContext(options: [.useLowQualityPower: false])

    func cloudImage(at time: CFTimeInterval, size: CGSize) -> CIImage? {
        guard let base = makeCloudTexture(size: CGSize(
            width: size.width * 2, height: size.height)) else { return nil }
        // 风速控制水平飘移速度,垂直方向给一个很小的分量模拟上升气流
        let windSpeed: CGFloat = 30   // 点每秒
        let dx = CGFloat(time) * windSpeed
            .truncatingRemainder(dividingBy: size.width)
        let drifted = base.transformed(by: CGAffineTransform(translationX: -dx, y: 0))
        let cropped = drifted.cropped(to: CGRect(origin: .zero, size: size))
        return applyCloudDensity(cropped, thickness: 0.7)
    }
}

驱动层用CADisplayLink每帧调用cloudImage(at:)并把结果交给CIContext渲染到Metal层或UIView。有一点必须强调:噪声滤镜是惰性求值的,如果每帧都重建整条滤镜链并重新生成噪声,GPU开销会显著上升。正确的做法是缓存噪声纹理的CIImage,每帧只修改末端的transform和密度参数,Core Image的kernel会复用已生成的噪声数据,帧耗可以从十几毫秒降到两毫秒以内。

性能上还有几个细节值得注意。第一,渲染尺寸不要直接用屏幕物理像素,云本身是低频内容,按逻辑分辨率渲染再由GPU缩放几乎无质量损失;第二,CIContext应当全局复用一个实例,频繁创建会反复分配GPU资源;第三,如果云飘速度很慢,可以把帧率锁定在30fps甚至更低,CADisplayLink的preferredFramesPerSecond属性即可控制,肉眼完全察觉不出卡顿,功耗却能下降近一半。

最后补充一种进阶玩法:将平移量同时作用于两个octave不同的噪声层,速度略作差异,两层云以不同速度飘动并叠加,会产生真实大气中不同高度云层的视差效果。实现上无非是重复第二节的处理流程,给每层独立的风速和厚度参数,这也是许多天气App做出“有深度天空”的秘密所在。

Core Image分形噪声iOS图像处理修改时间:2026-09-10 03:40:41

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0910/53785.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。