水纹(涟漪)特效壁纸——程序+实现原理
可执行程序
蓝奏云网盘:https://italink.lanzous.com/ihqhQd9ntrg
效果
桌面壁纸——超真实水波纹效果
实现工具: Qt+OpenGL
实现功能
- 模拟水波:生成水面波形,完成水面的光照折射计算
- 窗口嵌入桌面
- 监视顶层窗口是否遮挡桌面,是就停止水纹的刷新
- 全局鼠标钩子
原理
波形生成
把水面波形可以近似看作是一个以振源距离(dis)为参数的正弦波,其中A为最大振幅,F为频率,dis是当前点(xy)与振源的距离,本质上这是一个二元函数,通过这样一个函数,我们能构造出如下效果的曲面:
其中半截面就是一个普通的正弦函数:
这样就完成水面波形的计算了?很显然没这么简单,水面的波形并不只是一个简单的正弦波(博主也不清楚细节),但是通过观察一些水面效果,我们可以发现水波往往是只显示一小段圆环一样的波形,并且随着时间会向外部扩散。
所以我们要做什么呢?
我们需要突出显示正弦波的一小段,把其他部分抑制到几乎为0,显示的这一段会随着时间向外部扩散。我们可以通过改变最大振幅来实现这样的效果,也就是说我们需要让振幅不再是一个常量,而是一个函数,仔细想想,什么函数才能满足我们的需求呢?
当然是它——万能的高斯函数
高斯函数中:
- a表示最大振幅(峰值)
- b表示对称轴
- c与钟状的宽度有关
当a=1,b=10,c=2时,你能得到这样的图形
有了这个高斯函数,我们把它作为正弦函数的最大振幅(也即是两者相乘)
使用之前的参数,我们将会得到:
也就是大约会是这样的波形
为了做扩散,我们需要让高斯函数的对称轴与时间(T)进行关联,随着时间推移,对称轴也随之增大,也就是成正比,我们可以增加另一个变量V来控制扩散的速度
再通过变量W控制波纹的宽度。
综上,我们得到的水波纹的曲面方程是:
其中:
- A表示最大振幅
- V表示扩散速度
- T表示时间
- W表示宽度系数
- F表示频率
水面折射计算
在这一步,我们将计算图片上某一像素点的经过水面折射后实际应该输出的颜色,在OpenGL中,这部分代码在片段着色器中完成(因此上一步也是在片段着色器中)。
计算法向量
我们通过水波的一个半截面来做演示,人的视线是从上往下,大致上观察模型是这个样子的(虽然说光线是从水到空气再到人眼的,但为了推导,我们反过来把光线看作是从人眼发出的)
我们需要计算图片上某一像素点的经过水面折射后实际对应纹理图片的哪一位置
我们需要得到视线经过水面折射后的的方向,要得到这个计算,必须得到视线在水面上对应点(平面)的法向量,通过法向量,我们才能完成入射方向->折射方向的计算
由于通过水面我们是通过函数来构造的,按理说可以通过对函数求偏导来计算得到两个切向量,把它们叉乘就得到了点平面的法向量,但函数其实是非常复杂的,求导之后函数变得非常庞大,计算也比较困难,因此我们用一个投机取巧的方式来计算点平面的法向量:
我们通过求点平面附近两个不共线点的高度,组成两个方向向量,通过对它们求叉乘来计算法向量,这样得到是数据虽然不是很精确,但已经够用了,且效率也不低。
计算折射光线的方向
GLSL提供了一个函数refract(入射向量,法向量,折射相对系数)来计算折射
因此,我们知道了入射向量(0,0,-1)和法向量,求折射向量其实是很简单的,调用函数就行(水到空气的折射系数为4/3,约等于1.33)
计算坐标偏移
得到折射向量之后,我们只需要把折射向量的进行拉伸使得z值等于实际高度(水面高度+波形高度),就能得出经过水面折射后xy的偏移值,原来的坐标+偏移坐标就得到了水面折射后的坐标,另外由于纹理坐标的取值为[0,1],因此我们还需要根据窗口宽度做一个坐标标准化。
大功告成!
附上博主自己实现的片段着色器代码:
#version 330 core
out vec4 FragColor;uniform sampler2D texture;uniform vec3 data[50]; //data传递(鼠标x,鼠标y,运行时间):支持多振源
uniform int data_size; //当前有效的data长度
uniform vec2 screen_size; //屏幕尺寸
uniform float frequency; //频率
uniform float amplitude; //最大振幅
uniform float wave_width; //波纹的宽度
uniform float depth; //水平面距离背景图片的深度
uniform float speed;in vec2 TexCoord;void main()
{float height;float upHeight;float rightHeight;for(int i=0;i<data_size;i++){float time = data[i].z; //鼠标点击后的时间float dis = distance(data[i].xy,gl_FragCoord.xy); //鼠标位置到当前片段位置的距离float amplit = amplitude*pow(2.74,-(dis-time*speed)*(dis-time*speed)/2/(wave_width*wave_width))*sin(dis*frequency); //计算当前片段的振幅:这里利用高斯函数突出显示当前时间所显示的波形height += amplit*sin(dis*frequency); //当前波形的高度dis=distance(data[i].xy,gl_FragCoord.xy+vec2(0,1));upHeight += amplitude*pow(2.74,-(dis-time*speed)*(dis-time*speed)/2/(wave_width*wave_width))*sin(dis*frequency)*sin(dis*frequency);dis=distance(data[i].xy,gl_FragCoord.xy+vec2(1,0));rightHeight += amplitude*pow(2.74,-(dis-time*speed)*(dis-time*speed)/2/(wave_width*wave_width))*sin(dis*frequency)*sin(dis*frequency);}vec3 up = vec3(0,1,upHeight-height);vec3 right = vec3(1,0,rightHeight-height);vec3 normal = cross(up,right);vec3 view = vec3(0,0,-1);vec3 re = refract(view,normal,1.33);vec2 coordOffset = re.xy*((height+depth)/re.z)/screen_size;FragColor = texture2D(texture,TexCoord+coordOffset);
}
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
水纹(涟漪)特效壁纸——程序+实现原理相关推荐
- 【Unity】创建一个自己的AR脸部特效安卓程序
目录 1 创建一个换脸AR场景 2 下载官方提供的BasicFaceFilterAssets资源 3 设置AR面部追踪 4 配置AR Face Manager 5 配置AR Camera为前置摄像头 ...
- PHP网站安装程序的原理及代码
原文:PHP网站安装程序的原理及代码 原理: 其实PHP程序的安装原理无非就是将数据库结构和内容导入到相应的数据库中,从这个过程中重新配置连接数据库的参数和文件,为了保证不被别人恶意使用安装文件,当安 ...
- iOS程序启动原理(上)
为什么80%的码农都做不了架构师?>>> iOS程序启动原理 Info.plist 常见设置 建立一个工程后,会在Supporting files文件夹下看到一个"工 ...
- python解析器原理_Python程序运行原理图文解析
本文研究的主要是Python程序运行原理,具体介绍如下. 编译型语言(C语言为例) 动态型语言 一个程序是如何运行起来的?比如下面的代码 #othermodule.py def add(a, b): ...
- 程序执行原理(科普)
程序执行原理(科普) 目标 计算机中的 三大件 程序执行的原理 程序的作用 01. 计算机中的三大件 计算机中包含有较多的硬件,但是一个程序要运行,有 三个 核心的硬件,分别是: CPU 中央处理器, ...
- 制作简单的视频壁纸程序,C语言可完成
简易的壁纸程序 该实现来自于:https://www.bilibili.com/video/BV1HZ4y1978a 附上作者b站:偶尔有点小迷糊 (https://space.bilibili.co ...
- 微型计算机原理实验程序,微机原理实验(含程序).doc
微机原理实验(含程序) 微机原理实验(含程序) 实验一 基本I/O口扩展实验(请在实验课前写好预习报告) 实验目的: 1.了解并熟悉8086K实验系统 2.掌握汇编语言基本程序框架 实验内容: 1.利 ...
- Python03(注释、算术运算符、程序执行原理、变量使用)
注释 目标 注释的作用 单行注释(行注释) 多行注释(块注释) 01. 注释的作用 使用用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序的可读性 02. 单行注释(行注释) 以 # 开头,# ...
- iOS程序启动原理---iOS-Apple苹果官方文档翻译
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...
最新文章
- 交叉分解(Cross decomposition)、典型关联分析(Canonical Correlation Analysis,CCA)、偏最小二乘回归PLS
- 歌唱online活动目录数据库还原[为企业维护windows server 2008系列二]
- 数据结构-Hash总结(三):实践基础篇
- 内网穿透 --- frp
- C语言字符串分离数字和字母,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...
- python基础之玩转(变量赋值)
- 善用AI技术,旷视发布《人工智能应用准则》
- 解决:卸载anaconda后 cmd闪退或打不开
- Hadoop架构和原理
- 【黑马程序员】集合二
- [c#源码分享]TCP通信中的大文件传送
- 计算机毕业设计springboot+vue+elementUI校园志愿者管理系统
- 转载[UGUI]深入理解Canvas Scaler
- python overflowerror_Python中的OverflowError:(34,'结果太大')
- VUE项目初始化报[404 Not Found - GET https://r.cnpmjs.org/xxxx]
- 2017全国高校计算机大赛,我校在2017中国高校计算机大赛中获全国高校银奖
- 群晖DSM7.0设置群晖NAS域名外网访问
- 使用 Javascript 与 Flow 交互
- UNCTF2021 部分WP
- 【转】这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已
热门文章
- buu crypto 变异凯撒
- 蛙蛙推荐:蛙蛙牌关键词提取算法
- MATLAB编写用户登陆界面小结——更改界面左上角图标、输入用户名提醒和输入密码隐藏
- 端游开发用什么技术可以让用户更短时间内体验游戏?端游分发...
- 物理信息融合系统CPS---数据流(SDF/DDF)
- echart旭日图_echarts之用饼图制作带labelline的旭日图(一)
- precision与Recall
- c++ 小游戏 NO6 跑酷游戏
- Word文档 | 删除回车符
- 从第三方应用跳回uniapp开发的app