Flutter 小技巧之:实现 iOS 26 的 “液态玻璃”

随着 iOS 26 发布,「液态玻璃」无疑是热度最高的标签,不仅仅是因为设计风格大变,更是因为 iOS 26 beta1 的各种 bug 带来的毛坯感让 iOS 26 冲上热搜,比如通知中心和控制中心看起来就像是一个半成品:

当然,很多人可能说,不就是一个毛玻璃效果吗?实际上还真有些不大一样,特别是不同控件的“模糊”和“液态”效果都不大一样,效果好不好看一回事,但是液态玻璃确实不仅仅只是一个模糊图层,至少从下面这个锁屏效果可以看到它类似液态的扭曲变化:

image-20250612150709296

所以,在实现上就不可能只是一个简单的 blur ,类似效果肯定是需要通过自定义着色器实现,而恰好在 shadertoy 就有人发布了类似的实现,可以比较方便移植到 Flutter :

针对这个 shader ,其中 LiquidGlass 部分是实现磨砂玻璃效果的核心:

  • vec2 radius = size / R; 计算模糊的半径,将其从像素单位转换为标准化坐标。

  • vec4 color = texture(tex, uv); 获取当前像素 uv 处的原始颜色

  • for (float d = 0.0; d < PI; d += PI / direction): 外层循环,确定采样的方向,从 0 到 180 度进行迭代。

  • for (float i = 1.0 / quality; i <= 1.0; i += 1.0 / quality) 内层循环,沿着当前方向 d 进行多次采样, quality 越高,采样点越密集

  • color += texture(tex, uv + vec2(cos(d), sin(d)) * radius * i); 在当前像素周围的圆形区域内进行采样, vec2(cos(d), sin(d)) 计算出方向向量,radius * i 确定了沿该方向的采样距离,通过累加这些采样点的颜色,实际上是在对周围的像素颜色进行平均

  • color /= (quality * direction + 1.0); 将累加的颜色值除以总采样次数(以及原始颜色),得到平均颜色,这个平均过程就是实现模糊效果的过程

vec4 LiquidGlass(sampler2D tex, vec2 uv, float direction, float quality, float size) {vec2 radius = size / R;vec4 color = texture(tex, uv);for (float d = 0.0; d < PI; d += PI / direction) {for (float i = 1.0 / quality; i <= 1.0; i += 1.0 / quality) {color += texture(tex, uv + vec2(cos(d), sin(d)) * radius * i);}}color /= (quality * direction + 1.0); // +1.0 for the initial colorreturn color;
}

而在着色器的入口,它会将所有部分组合起来渲染,其中关键在于下方代码,这是实现边缘液体感的处理部分:

#define S smoothstepvec2 uv2 = uv - uMouse.xy / R;
uv2 *= 0.5 + 0.5 * S(0.5, 1.0, icon.y);
uv2 += uMouse.xy / R;

它不是直接用 uv 去采样纹理,而是创建了一个被扭曲的新坐标 uv2icon.y 是前面生成的位移贴图,smoothstep 函数利用这个贴图来计算一个缩放因子。

在图标中心(icon.y 接近 1),缩放因子最大,使得 uv2 的坐标被推离中心,产生放大/凸起的效果,就像透过一滴水或一个透镜看东西一样,从而实现视觉上的折射效果。

最后利用 mix 把背景图片混合进来,其中 LiquidGlass(uTexture, uv2, ...) 通过玻璃效果使用被扭曲的坐标 uv2 去采样并模糊背景:

vec3 col = mix(texture(uTexture, uv).rgb * 0.8,0.2 + LiquidGlass(uTexture, uv2, 10.0, 10.0, 20.0).rgb * 0.7,icon.x
);

所以里实现的思路是扭曲的背景 + 模糊处理,我们把中间的 icon 部分屏蔽,换一张人脸图片,可以看到更明显的边缘扭曲效果:

image-20250612151557905

当然,这个效果看起来并不明显,我们还可以在这个基础上做修改,比如屏蔽 uv2 *= 0.5 + 0.5 * S(0.5, 1.0, icon.y),调整为从中间进行放大扭曲:

//uv2 *= 0.5 + 0.5 * S(0.5, 1.0, icon.y);// 使用 mix 函数,以 icon.x (方块形状) 作为混合因子
// 在方块外部 (icon.x=0),缩放为 1.0 (不扭曲)
// 在方块内部 (icon.x=1),缩放为 0.8 (最大扭曲)
uv2 *= mix(1.0, 0.8, icon.x);

通过调整之后,实际效果可以看到变成从中间放大扭曲,从眼神扭曲上看起来更接近锁屏里的效果:

当然,我们还可以让扭曲按照类似水滴从中间进行扭曲,来实现非平均的液态放大:

 //vec2 uv2 = uv - uMouse.xy / R;//uv2 *= 0.5 + 0.5 * S(0.5, 1.0, icon.y);//uv2 += uMouse.xy / R;// ================== 新的水滴扭曲 ==================// 1. 计算当前像素到鼠标中心点的向量 (在 st 空间)
vec2 p = st - M;// 2. 计算该点到中心的距离
float dist = length(p);// 3. 定义水滴效果的作用半径 (应与方块大小一致)
float radius = PX(100.0);// 4. 计算“水滴凸起”的强度因子 (bulge_factor)
//    我们希望中心点 (dist=0) 强度为 1,边缘点 (dist=radius) 强度为 0。
//    使用 1.0 - smoothstep(...) 可以创造一个从中心向外平滑衰减的效果,模拟水滴的弧度。
float bulge_factor = 1.0 - smoothstep(0.0, radius, dist);// 5. 确保该效果只在我们的方块遮罩 (icon.x) 内生效
bulge_factor *= icon.x;// 6. 定义中心点的最大缩放量 (0.5 表示放大一倍,值越小放大越明显)
float max_zoom = 0.5;// 7. 使用 mix 函数,根据水滴强度因子,在 "不缩放(1.0)" 和 "最大缩放(max_zoom)" 之间插值
//    中心点 bulge_factor ≈ 1, scale ≈ max_zoom (放大最强)
//    边缘点 bulge_factor ≈ 0, scale ≈ 1.0 (不放大)
float scale = mix(1.0, max_zoom, bulge_factor);// 8. 应用这个非均匀的缩放效果
vec2 uv2 = uv - uMouse.xy / R; // 将坐标中心移到鼠标位置
uv2 *= scale;                  // 应用计算出的缩放比例
uv2 += uMouse.xy / R;          // 将坐标中心移回

使用这个非均匀的缩放效果,可以看到效果更接近我们想象中的液态 “放大”:

如下图所示,最终看起来也会更想水面的放大,同时边缘的“高亮”也显得更加明显:

当然,这里的实现都是非常粗糙的复刻,仅仅只是自娱自乐,不管是性能还是效果肯定和 iOS 26 的液态玻璃相差甚远,就算不考虑能耗,想在其他平台或者框架实现类似效果的成本并不低,所以单从技术实现上来说,能用液态玻璃风格作为系统 UI,苹果应该是对于能耗控制和渲染成本控制相当自信才是

最后,如果感兴趣的可以直接通过下方链接获取 Demo :

  • https://github.com/CarGuo/gsy_flutter_demo/blob/master/lib/widget/liquid_glass_demo.dart

  • https://github.com/CarGuo/gsy_flutter_demo/blob/master/lib/widget/liquid_glass_demo2.dart

  • https://github.com/CarGuo/gsy_flutter_demo/tree/master/shaders

参考链接:

  • https://www.shadertoy.com/view/WftXD2

  • https://rive.app/marketplace/20904-39287-liquid-glass/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/909393.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android工程中FTP加密传输与非加密传输的深度解析

详细的FTP传输实现方案&#xff0c;包括完整代码、安全实践、性能优化和实际应用场景分析。 一、FTP传输类型对比表&#xff08;增强版&#xff09; 特性非加密FTPFTPS (FTP over SSL/TLS)SFTP (SSH File Transfer Protocol)协议基础FTP (RFC 959)FTP SSL/TLS (RFC 4217)SSH…

C# 枚 举(枚举)

枚举 枚举是由程序员定义的类型&#xff0c;与类或结构一样。 与结构一样&#xff0c;枚举是值类型&#xff1a;因此直接存储它们的数据&#xff0c;而不是分开存储成引用和数据。枚举只有一种类型的成员&#xff1a;命名的整数值常量。 下面的代码展示了一个示例&#xff0c…

一文详解前缀和:从一维到二维的高效算法应用

文章目录 一、一维前缀和​1. 基本概念​2. C 代码实现​3. 应用场景​ 二、二维前缀和1. 基本概念​2. C 代码实现​3. 应用场景​ 三、总结​ 在算法竞赛和日常的数据处理工作中&#xff0c;前缀和是一种极其重要的预处理技术。它能够在常数时间内回答多次区间查询&#xff0…

windows 开发

文章目录 环境搭建数据库关键修改说明&#xff1a;在代码中使用该连接字符串&#xff1a;注意事项&#xff1a;实际使用 都说几天创造一个奇迹&#xff0c;现在是真的这样了&#xff0c;Just do it! 环境搭建 数据库 需要下载这个SQL Server数据库&#xff0c;然后每次Visua…

免费OCPP协议测试工具

免费OCPP 1.6J协议测试工具&#xff0c;简单实用。除加密功能外&#xff08;后续版本支持&#xff09;&#xff0c;支持所有消息调试。 后续将添加2.01和和2.1协议支持. 欢迎使用 Charge-Test

高等数学基础(行列式和矩阵的秩)

行列式主要用于判断矩阵是否可逆及计算特征方程 初见行列式 行列式起源于线性方程组求解 { a 11 x 1 a 12 x 2 b 1 a 21 x 1 a 22 x 2 b 2 \begin{cases} a_{11}x_1 a_{12}x_2 b_1 \\ a_{21}x_1 a_{22}x_2 b_2 \end{cases} {a11​x1​a12​x2​b1​a21​x1​a22​x2…

开心灿烂go开发面试题

1.给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例1: 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] package main import “fmt” type ListNode struct { Val int Next *ListNode } func main() { l1 : &…

【Flutter】程序报错导致的灰屏总结

【Flutter】程序报错导致的灰屏总结 一、前言 在 Flutter 中&#xff0c;出现“灰屏”&#xff08;grey screen&#xff09;通常意味着 应用发生了未捕获的错误&#xff0c;导致框架无法正确构建 UI。 这也是在面试过程中常常问到的。 二、错误分类 常见的会导致灰屏的错误…

基于物联网设计的智慧家庭健康医疗系统

1. 项目开发背景 随着物联网&#xff08;IoT&#xff09;技术的发展&#xff0c;智能家居系统逐渐融入到我们的日常生活中&#xff0c;成为提高生活质量、增强家庭安全、提升健康管理的重要工具。特别是在健康医疗领域&#xff0c;借助物联网技术&#xff0c;智能家居不仅能够…

设计模式精讲 Day 1:单例模式(Singleton Pattern)

【设计模式精讲 Day 1】单例模式&#xff08;Singleton Pattern&#xff09; 文章内容 开篇 在软件开发中&#xff0c;设计模式是解决常见问题的通用解决方案。作为“设计模式精讲”系列的第一天&#xff0c;我们将深入讲解单例模式&#xff08;Singleton Pattern&#xff09…

【卫星通信】3GPP标准提案:面向NB-IoT(GEO)场景的IMS信令优化方案-降低卫星通信场景下的语音呼叫建立时延

一、引言 随着5G非地面网络&#xff08;NTN&#xff09;技术的演进&#xff0c;基于NB-IoT的卫星通信&#xff08;如GEO地球同步轨道卫星&#xff09;逐渐成为偏远地区语音服务的重要补充。然而&#xff0c;传统IP多媒体子系统&#xff08;IMS&#xff09;的信令流程在带宽受限…

软件测试之简单基础的安全测试方法(另外包含软测面试题库)

文章目录 前言安全测试是什么简单基础的安全测试方法密码安全操作权限验证SQL注入xss脚本攻击文件上传下载安全漏洞扫描Web扫描APP扫描 面试题库&#xff08;仅参考&#xff09;参考目录 前言 阅读本文前请注意最后编辑时间&#xff0c;文章内容可能与目前最新的技术发展情况相…

LCEL:LangChain 表达式语言详解与测试工程师的实践指南

引言 在 AI 应用开发中&#xff0c;如何高效地组合多个步骤&#xff08;如提示模板、模型调用、输出解析&#xff09;并优化执行流程&#xff0c;是开发者和测试工程师共同面临的挑战。LangChain Expression Language (LCEL) 作为 LangChain 的核心功能之一&#xff0c;提供了…

LeetCode面试经典150题—旋转数组—LeetCode189

原题请见&#xff1a;Leetcode189-旋转数组 1、题目描述 2、题目分析 首先容易想到的最简单的方案&#xff0c;是算出来移动K步之后&#xff0c;新数组的每一个坐标与原坐标的映射关系&#xff0c;然后根据映射关系放到一个全新的数组&#xff0c;再把新数组的值赋给原数组。…

2.5 Rviz使用教程

新建终端&#xff0c;键入命令 roslaunch wpr_simulation wpb_simple.launch 再新建终端&#xff0c;键入命令 rviz修改Fix Frame 为 base_footprint 点击add之后选择RobotModel 再增加一个LaserScan 选择激光雷达话题 可视化效果 配置的两种方法 1.在Gazebo运行的基础上&…

基于SpringBoot+JSP开发的招投标采购信息平台

角色&#xff1a; 管理员、普通用户 技术&#xff1a; 后端&#xff1a;Spring Boot Mybatis-Plus MySQL 前端&#xff1a;JSP 核心功能&#xff1a; 该平台是一个用于管理投标和招标信息的系统&#xff0c;主要提供信息发布、用户管理和交易管理等核心功能。 功能介绍…

【项目实训#10】HarmonyOS API文档RAG检索系统后端实现

【项目实训#10】HarmonyOS API文档RAG检索系统后端实现 文章目录 【项目实训#10】HarmonyOS API文档RAG检索系统后端实现一、背景简介二、RAG技术原理与架构设计2.1 RAG技术原理回顾与提升2.2 系统架构设计 三、RAG引擎核心实现3.1 RAG引擎初始化3.2 查询向量化3.3 文档检索实现…

专注于PLC数据采集MES交互解决方案

专注于PLC数据采集MES交互解决方案 前篇文章我们讲到当下的制造行业在工业4.0的大趋势下&#xff0c;MES系统成为现场制造过程管制的有利武器&#xff0c;更是质量追踪的一把好工具。我们要知道产品在各个加工环节的结果。除了人工在各个制造环节录入制造结果外&#xff0c;更…

微信小程序实现文字逐行动画效果渲染显示

1. 微信小程序实现文字逐行动画效果渲染显示 在微信小程序开发中,为了文字逐行动画效果渲染可以通过JavaScript 和 WXML 的动态数据绑定来实现,实现文字逐行显示的效果,同时结合 CSS 动画提升视觉体验。   如果需要更复杂的动画效果(如缩放、移动等),可以使用微信小程序…

Redux 原理深度剖析

1. Redux 实现 定义 Action 和 Reducer 类型&#xff0c;为了简便&#xff0c;先用JavaScript来演示。 1.1. 定义Action和Reducer类型 // 定义 Action 类型 /*** typedef {Object} Action* property {string} type*/// 定义 Reducer 类型 /*** callback Reducer* param {any…