【html】iOS26 液态玻璃实现效果

 

 

<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>液体玻璃效果演示</title><style>body {margin: 0;overflow: hidden;background-color: #000;}canvas {display: block;width: 100vw;height: 100vh;}/* 控制面板 */#controls {position: absolute;top: 10px;left: 10px;padding: 10px;background-color: rgba(0, 0, 0, 0.5);color: white;font-family: sans-serif;border-radius: 5px;user-select: none;}#controls label {cursor: pointer;}</style></head><body><canvas id="glslCanvas"></canvas><imgid="backgroundImage"src="https://pic2.zhimg.com/v2-a53c740141ab75eb4fe16af3ef8c35c5_r.jpg"crossorigin="anonymous"style="display: none"/><div id="controls"><label><input type="checkbox" id="useCircleCheckbox" />使用圆形</label></div><script id="vertex-shader" type="x-shader/x-vertex">// 将顶点位置传递出去,这样片段着色器就可以在构成平面的两个三角形上运行attribute vec2 a_position;void main() {gl_Position = vec4(a_position, 0.0, 1.0);}</script><script id="fragment-shader" type="x-shader/x-fragment">precision mediump float; // 为浮点数设置中等精度// 从 JavaScript 传入的变量uniform vec3 iResolution;uniform float iTime;uniform vec4 iMouse;uniform vec3 iImageResolution;uniform sampler2D iImage1;uniform float useCircle;// 已适配 WebGL ---vec2 R;const float PI = 3.14159265;// 创建旋转矩阵mat2 Rot(float a) {float c = cos(a);float s = sin(a);return mat2(c, -s, s, c);}// 像素归一化处理float PX(float a) {return a / R.y;}// 矩形距离场float Box(vec2 p, vec2 b) {vec2 d = abs(p) - b;return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);}// 圆形距离场float Circle(vec2 p, float r) {return length(p) - r;}// 根据 useCircle 选择形状(圆形或圆角矩形)float Shape(vec2 p, vec2 b, float r) {return useCircle > 0.5 ? Circle(p, r) : Box(p, b);}// 液体玻璃效果vec4 LiquidGlass(vec2 uv, float direction, float quality, float size) {vec2 radius = size / R;vec4 color = texture2D(iImage1, uv);float d_step = PI / direction; // 方向步长float i_step = 1.0 / quality;  // 质量步长float d = 0.0;// 循环被展开以兼容一些旧的GPUfor (int j = 0; j < 10; j++) {if (float(j) >= direction) break;float i = i_step;for (int k = 0; k < 10; k++) {if (float(k) >= quality) break;color += texture2D(iImage1, uv + vec2(cos(d), sin(d)) * radius * i);i += i_step;}d += d_step;}color /= quality * direction + 1.0; // 归一化return color;}// 形状扭曲效果vec4 Distortion(vec2 uv) {float shape = Shape(uv, vec2(PX(50.0)), PX(50.0));float shapeShape = smoothstep(PX(1.5), 0.0, shape - PX(50.0)); // 形状平滑过渡float shapeDisp = smoothstep(PX(75.0), 0.0, shape - PX(25.0)); // 边框宽度float shapeLight = shapeShape * smoothstep(0.0, PX(20.0), shape - PX(40.0)); // 光照强度return vec4(shapeShape, shapeDisp, shapeLight, 0.0);}void main() {R = iResolution.xy;vec2 uv = gl_FragCoord.xy / R; // 归一化UV坐标vec2 st = (gl_FragCoord.xy - 0.5 * R) / R.y; // 屏幕空间坐标vec2 M = iMouse.xy == vec2(0.0) ? vec2(0.0) : (iMouse.xy - 0.5 * R) / R.y; // 鼠标位置// 如果鼠标没有移动过,则将效果定位在中心if (iMouse.x == 0.0 && iMouse.y == 0.0) {M = vec2(0.0);}vec4 dist = Distortion(st - M); // 计算扭曲效果vec2 uv2 = uv;uv2 *= 0.5 + 0.5 * smoothstep(0.5, 1.0, dist.y); // 缩放UVvec3 col = mix(vec3(0.0), // 透明黑色背景0.2 + LiquidGlass(uv2, 10.0, 10.0, 5.0).rgb * 0.7, // 应用液体玻璃效果dist.x); // 根据图标形状混合col += dist.z * 0.9 + dist.w; // 添加图标光照和图案// 应用阴影效果col *= 1.0 - 0.2 * smoothstep(PX(80.0), 0.0, Shape(st - M + vec2(0.0, PX(40.0)), vec2(PX(50.0)), PX(50.0)));// 使用 dist.x 控制透明度:图标区域不透明,其他区域透明float alpha = dist.x;gl_FragColor = vec4(col, alpha); // 返回最终颜色和透明度}</script><script>const canvas = document.getElementById('glslCanvas');const gl = canvas.getContext('webgl');if (!gl) {alert('抱歉,您的浏览器不支持 WebGL。');}// 获取 DOM 元素const backgroundImage = document.getElementById('backgroundImage');const useCircleCheckbox = document.getElementById('useCircleCheckbox');// 创建着色器程序function createShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);if (success) {return shader;}console.error(gl.getShaderInfoLog(shader));gl.deleteShader(shader);}const vertexShaderSource = document.getElementById('vertex-shader').text;const fragmentShaderSource =document.getElementById('fragment-shader').text;const vertexShader = createShader(gl,gl.VERTEX_SHADER,vertexShaderSource);const fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentShaderSource);function createProgram(gl, vertexShader, fragmentShader) {const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);const success = gl.getProgramParameter(program, gl.LINK_STATUS);if (success) {return program;}console.error(gl.getProgramInfoLog(program));gl.deleteProgram(program);}const program = createProgram(gl, vertexShader, fragmentShader);gl.useProgram(program);// 准备数据 获取 uniform 和 attribute 的位置const positionAttributeLocation = gl.getAttribLocation(program,'a_position');const resolutionUniformLocation = gl.getUniformLocation(program,'iResolution');const timeUniformLocation = gl.getUniformLocation(program, 'iTime');const mouseUniformLocation = gl.getUniformLocation(program, 'iMouse');const imageResolutionUniformLocation = gl.getUniformLocation(program,'iImageResolution');const imageSamplerUniformLocation = gl.getUniformLocation(program,'iImage1');const useCircleUniformLocation = gl.getUniformLocation(program,'useCircle');// 创建一个缓冲区来放置一个覆盖整个画布的矩形const positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);const positions = [-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1];gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);gl.enableVertexAttribArray(positionAttributeLocation);gl.vertexAttribPointer(positionAttributeLocation,2,gl.FLOAT,false,0,0);// 设置纹理let imageTexture;backgroundImage.onload = function () {imageTexture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D, imageTexture);// 设置纹理参数gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);// 将图片数据上传到纹理gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,backgroundImage);// 设置图像分辨率 uniformgl.uniform3f(imageResolutionUniformLocation,backgroundImage.width,backgroundImage.height,0);// 启动渲染requestAnimationFrame(render);};// 如果图片已经加载完成 (例如从缓存加载)if (backgroundImage.complete) {backgroundImage.onload();}// 渲染循环let startTime = Date.now();let mouseX = 0;let mouseY = 0;function render(time) {// 调整画布大小以匹配显示大小const displayWidth = gl.canvas.clientWidth;const displayHeight = gl.canvas.clientHeight;if (gl.canvas.width !== displayWidth ||gl.canvas.height !== displayHeight) {gl.canvas.width = displayWidth;gl.canvas.height = displayHeight;gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);}gl.clearColor(0, 0, 0, 0);gl.clear(gl.COLOR_BUFFER_BIT);// 更新 uniformsgl.uniform3f(resolutionUniformLocation,gl.canvas.width,gl.canvas.height,1.0);gl.uniform1f(timeUniformLocation, (Date.now() - startTime) * 0.001);gl.uniform4f(mouseUniformLocation,mouseX,gl.canvas.height - mouseY,0,0); // y坐标需要翻转gl.uniform1f(useCircleUniformLocation,useCircleCheckbox.checked ? 1.0 : 0.0);// 绑定纹理gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, imageTexture);gl.uniform1i(imageSamplerUniformLocation, 0);// 绘制gl.drawArrays(gl.TRIANGLES, 0, 6);// 请求下一帧requestAnimationFrame(render);}// 事件监听window.addEventListener('mousemove', (e) => {mouseX = e.clientX;mouseY = e.clientY;});</script></body>
</html>

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

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

相关文章

探索算法秘境:量子随机游走算法及其在图论问题中的创新应用

目录 ​编辑 一、量子随机游走算法的起源与原理 二、量子随机游走算法在图论问题中的创新应用 三、量子随机游走算法的优势与挑战 四、结语 在算法研究的浩瀚星空中&#xff0c;总有一些领域如同遥远星系&#xff0c;闪烁着神秘而诱人的光芒。今天&#xff0c;我们将一同深…

C# 一维数组和矩形数组全解析

在编程的世界里&#xff0c;数组是一种非常重要的数据结构。今天&#xff0c;我们就来详细了解一下一维数组和矩形数组。 数组基础认知 数组实例是从 System.Array 继承类型的对象。由于它从 BCL 基类派生而来&#xff0c;所以继承了许多有用的成员&#xff1a; Rank 属性&a…

WebStorm编辑器侧边栏

目录 编辑器侧边栏行号配置行号隐藏行号 代码折叠侧边栏图标书签添加匿名书签添加助记符书签 运行和调试管理断点配置断点图标 版本控制配置Git Blame注释 编辑器侧边栏 编辑器左侧的垂直区域。当编写代码时&#xff0c;提供重要信息和操作图标。外观和行为可以根据你的喜好进…

腾讯云TCCA认证考试报名 - TDSQL数据库交付运维工程师(PostgreSQL版)

数据库交付运维工程师-腾讯云TDSQL(PostgreSQL版)认证 适合人群&#xff1a; 适合从事TDSQL(PostgreSQL版)交付、运维、售前咨询以及TDSQL(PostgreSQL版)相关项目的管理人员。 认证考试 单选*40道多选*20道 成绩查询 70分及以上通过认证&#xff0c;官网个人中心->认证考…

attn_mask 为 (1, 1) 时什么意思? 7,7又是什么意思?

在深度学习中&#xff0c;特别是在 Transformer 模型和注意力机制&#xff08;Attention Mechanism&#xff09;中&#xff0c;attn_mask&#xff08;注意力掩码&#xff09;是一个用于控制注意力计算的张量。它决定了在计算注意力分数时&#xff0c;哪些位置应该被关注&#x…

Qt联合Halcon开发二:Halcon窗口绑定Qt控件显示Hobject图像【详细图解流程】

1. 项目准备 在本项目中&#xff0c;我们将使用Qt框架与Halcon库结合&#xff0c;展示图像并进行图像处理。首先&#xff0c;确保你已经配置好Qt和Halcon的开发环境。 环境配置可查看上篇文章 2. 创建Qt界面 在Qt中&#xff0c;创建一个窗口并拖入按钮和Graphics View控件。G…

Redis 持久化机制详解:RDB、AOF 原理与面试最佳实践(AOF篇)

在上一章我们深入学习了 Redis 中重要的数据持久化机制 ——RDB&#xff08;Redis Database&#xff09;&#xff0c;了解了其通过周期性快照将数据以二进制文件形式保存到磁盘的原理&#xff0c;包括触发条件、文件结构以及优缺点等核心内容。 Redis 持久化机制详解&#xff…

【GateWay】和权限验证

【GateWay】网关详解和权限验证 一、Gateway 核心概念与架构二、路由断言&#xff08;Route Predicates&#xff09;详解三、过滤器&#xff08;Filters&#xff09;机制四、权限认证的核心理论模型五、Spring Cloud Gateway Security OAuth2 集成方案六、OAuth2.0 集成 一、…

QSqlDatabase: QSQLITE driver not loaded

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言可能的原因解决办法1. 确认 SQLite 驱动插件文件2. 拷贝插件文件到应用程序目录3. 设置插件搜索路径4. 安装 SQLite 依赖库5. 解决 QCoreApplication 实例问题 …

20250619在荣品的PRO-RK3566开发板的Android13下解决海罗光电有限公司HL070T58C-05屏在启动的时候出现白色条纹的问题【时序】

20250619在荣品的PRO-RK3566开发板的Android13下解决海罗光电有限公司HL070T58C-05屏在启动的时候出现白色条纹的问题 2025/6/19 20:39 缘起&#xff1a;荣品的PRO-RK3566开发板的Android13下&#xff0c;点亮海罗光电有限公司HL070T58C-05屏。 在启动的时候会出现花屏/白色条纹…

docker使用Volume对Nginx进行挂载

需求&#xff1a; 需要将Nginx的欢迎页面也就是index.html文件进行修改。 原始方法&#xff1a;由于docker会为每一个容器创建其对应的文件信息&#xff0c;但是创建的信息内容只有其最基础的运行信息&#xff0c;所以想要直接去访问其index.html就无法做到。 使用volume&am…

基于springboot的宠物服务预约系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

idea 2025会在用户目录创建IdeaSnapshots文件夹

推荐一个api管理测试工具 一个简单的API测试和编写文档的工具 idea 2025会在用户目录创建IdeaSnapshots文件夹 解决方案 打开 Profiler 点击 setting 参考 https://youtrack.jetbrains.com/articles/SUPPORT-A-1086/How-to-change-or-turn-off-the-IdeaSnapshots-folder-…

【Mini-F5265-OB开发板试用测评】2、PWM驱动遥控车RX2接收解码带马达驱动控制IC

手头有带转向电机和动力电机小车底盘&#xff0c;买了很久一直在吃灰。 最近查了一下小车的驱动IC是富满微的8D420L,是一款传统的RX2接收解码芯片&#xff0c;带马达驱动。 手头没有TX2发送芯片&#xff0c;所以考虑用MCU直接发送PWM直接接入RX2&#xff0c;可能可以驱动。 一…

Tcpdump网络抓包工具详解!

一、简介 tcpdump就是&#xff1a;dump the traffic on a network&#xff0c;根据使用者的定义对网络上的数据包进行截获的包分析工具。 tcpdump是一个用于截取网络分组&#xff0c;并输出分组内容的工具。凭借强大的功能和灵活的截取策略&#xff0c;使其成为类UNIX系统下用…

Spring Boot的Security安全控制——应用SpringSecurity!

应用Spring Security 前面介绍了在项目开发时为什么选择Spring Security&#xff0c;还介绍了它的原理。本节开始动手实践Spring Security的相关技术。 实战&#xff1a;Spring Security入门 现在开始搭建一个新项目&#xff0c;实践一个Spring Security的入门程序。 &…

FPGA基础 -- Verilog行为级建模之alawys语句

Verilog 中的 always 语句块&#xff0c;这是行为级建模的核心结构之一&#xff0c;在 RTL 级设计中广泛用于时序逻辑和组合逻辑的建模。 一、什么是 always 语句&#xff1f; ✅ 定义&#xff1a; always 语句用于描述可综合的硬件行为逻辑&#xff0c;表示一个**“事件驱动…

【力扣 简单 C】704. 二分查找

目录 题目 解法一&#xff1a;二分查找 题目 解法一&#xff1a;二分查找 int find(const int* nums, int size, int target) {int left 0, right size - 1;while (left < right){int mid (left right) / 2;if (nums[mid] < target)left left 1;else if (nums[m…

Java并发编程实战 Day 30:并发编程未来展望与最佳实践总结

【Java并发编程实战 Day 30】并发编程未来展望与最佳实践总结 文章简述 经过30天的系统学习&#xff0c;我们从Java并发编程的基础知识逐步深入到高并发系统的架构设计与性能优化。本文作为“Java并发编程实战”系列的收官之作&#xff0c;将全面回顾整个系列的核心内容&#…

量化面试绿皮书:23. 醉酒乘客

文中内容仅限技术学习与代码实践参考&#xff0c;市场存在不确定性&#xff0c;技术分析需谨慎验证&#xff0c;不构成任何投资建议。 23. 醉酒乘客 100名乘客排队登机&#xff0c;每人持有一张对应座位的机票&#xff08;第n位乘客的座位号为n&#xff09;。 第一位乘客喝醉后…