前言

在学习opengl的过程中,经一前辈的教导,做出了一个比较有趣的东西:仿制Mac中窗口最小化的动画效果。因为是在我学习opengl的过程中制作的一个东西,所以实现的代码是使用是opengl来实现的,个人感觉思路也适用于其他的框架。实现的核心都在片元着色器中:对片元的uv坐标进行修改,从而模拟实现一个图片变形的整个过程。核心代码只有几句,刚做出来的时候自己也觉得太神奇了,所以希望把这个方法分享出来。

方法介绍

效果展示

首先给上一下最终做出来的一个效果吧~

上面实例用到的只是一个简单的矩形加一张贴图,这些大家就自己渲染好吧。本文主要是为了分享实现Mac窗口最小化的效果,所以有关opengl的一些渲染过程就不在本文多余的进行介绍了(默认大家都了解了,如果有需要源码的话后面可以在评论区留一下言,到时候我看到了再给大家分享出来把~)。可以给大家贴一下顶点坐标:

float vertices[] = {// 顶点坐标        uv坐标1.0f, 1.0f, 0.0f, 1.0f,1.0f,  // 右上角1.0f, -1.0f, 0.0f, 1.0f,0.0f, // 右下角-1.0f, 1.0f, 0.0f, 0.0f,1.0f, // 左上角1.0f, -1.0f, 0.0f, 1.0f,0.0f, // 右下角-1.0f, -1.0f, 0.0f, 0.0f,0.0f,// 左下角-1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上角
};

核心思路

由效果图可以看到,这整个动画的变化过程实际上就是一个矩形顶点在x方向上的变化和y方向上的变化, 大家看到这可能有不同的一个想法,比如对顶点坐标进行移动,但是这需要注意的是因为顶点着色器中拿到的只是上面的六个顶点坐标,如果需要做出一个曲线的伸缩效果,光对这些坐标进行移动是不足够的,因为光栅化过程中使用的是一个线性插值,所以如果需要通过顶点着色器中对这些顶点的位置进行移动,就需要加入更多的顶点才可以,那整个过程就变得有点繁琐了。
这里选择在片元着色器中进行变换,因为片元着色器可以获得uv坐标,通过改变uv的坐标可以改变取样的值(对眼睛来说就是显示出来的图片发现了改变),同时在渲染管线中到片元着色器中的时候已经生成了一个个的片元(类似像素一样),所以我们得到了更多的数据,这样不需要人为的加入顶点数据便可以生成平滑曲线形状。这里变换的原理实际上就是对uv坐标进行变换,拿u坐标(水平方向)来说,把水平方向的取样坐标像两边拉伸,让本来取样坐标应该为0和1的地方往中间去靠拢,然后取样坐标超出0~1的地方都让他不取样或者取样为透明的颜色(这样看起来就像是图片没有了),这样整体看起来就像是图片往中间收缩了。

因为uv坐标取样值范围是0 ~ 1,为了方便计算这里假设像素点的x坐标和y坐标的取样范围也是0 ~ 1,因为无论缩放前还是缩放后图片都应该被完整的显示出来的,所以变换前和变换后的像素点坐标都应该是成比例的,这样就可以知道收缩后的坐标(pos)的uv对应的是收缩前的哪个点(target)的uv,拿x坐标来计算,即target.x:

因为uv坐标的范围是0 ~ 1,像素点的坐标xy的范围也是0 ~ 1,而且是一 一对应的,所以算出来的target.x的值实际上也等于target点的u坐标,所以我们就知道了目标点的 u 坐标,然后根据该点当前的u坐标和target点的 u 坐标根据时间 t 进行线性插值,就可以得到x方向上的一个变化效果:

 float targetX = (TexCoord.x - Left.x) / (Right.x - Left.x);vec2 targetUV = vec2 (lerp(TexCoord.x,targetX , pow(1 - TexCoord.y,2) * time),TexCoord.y);


到了这一步图片虽然看起来收缩了,但是只是竖直的去搜索,这样得出来的效果跟预期有点差距,我们想要搜索边缘呈现一个曲线的效果,越往下搜索的幅度越大,所以我们需要对时间 t 乘以 y 坐标的一个的二次函数,因为y坐标和v坐标是一一对应的,所以实际上等同于乘以v坐标的一个二次函数:

 float targetX = (TexCoord.x - Left.x) / (Right.x - Left.x);vec2 targetUV = vec2 (lerp(TexCoord.x,targetX , pow(1 - TexCoord.y,2) * time),TexCoord.y);

这样一来水平方向上就得到了我们想要的一个收缩效果

接着只需要按相同思路去对y方向上进行搜索就可以了,这里就不在重复去讲了,后面直接我会直接把着色器的代码贴出来给大家,最后的效果图:

代码展示

因为实现动画的方法全部在着色器中,所以这里只展示着色器的代码,opengl的一些渲染流程的代码我这里就不贴出来了,后面大家需要的话可以在评论区留一下言,有人要的话我再贴出来的吧!~
需要提醒的是这个方法需要基于条件超出0~1范围的uv坐标为用户指定的边缘颜色。 所以在渲染之前需要把纹理的环绕方式设置一下,不同的渲染库有不同的方法,opengl的代码我这里贴一下:

     float borderColor[] = { 0.2f, 0.3f, 0.3f, 1.0f }; //指定边缘颜色,设置成跟背景同样的颜色就可以了glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); //指定环绕方式为"超出的坐标为用户指定的边缘颜色"glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

顶点着色器(vertexShader)的代码:

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;void main()
{gl_Position = vec4(aPos, 1.0);TexCoord = aTexCoord;
}

片元着色器(fragementShader)的代码:

out vec4 FragColor; in vec2 TexCoord;
uniform sampler2D ourTexture;
uniform float time;
uniform vec2 Left;
uniform vec2 Right;float lerp(float curentVal,float targetVal, float t)
{return targetVal * t + curentVal * (1-t);
}vec2 calTexCoord(vec2 texCoord){float targetX = (TexCoord.x - Left.x) / (Right.x - Left.x);float targetY = TexCoord.y * ( 1 / pow(1- max(2 * time -1,0),2));vec2 targetUV = vec2 (lerp(TexCoord.x,targetX , pow(1 - TexCoord.y,2) * time),targetY );return targetUV;
}void main()
{FragColor = texture(ourTexture,calTexCoord(TexCoord));
}
``

实现Mac窗口最小化动画效果相关推荐

  1. html5 窗口 最小化,HTML5 窗口最小化动画(先压扁后变窄)

    CSS 语言: CSSSCSS 确定 * { box-sizing: border-box; padding: 0; margin: 0; font-family: sans-serif; font- ...

  2. javascript实现仿苹果电脑窗口最小化效果、css实现不规则图形的div

    今天值班,继续分享个没用的技术,最近一个微信闲聊群的网友问能不能用div实现类似于苹果电脑窗口最小化的动画效果(窗口边框变得向内弯曲同时快速缩小直至消失),大概想了下,如果要完全还原,要用canvas ...

  3. java swing最小化_Java swing 窗口最小化到任务栏 点击右键显示菜单(复制代码即可运行查看效果)...

    Java swing 窗口最小化到任务栏 点击右键显示菜单(复制代码即可运行查看效果) package swing; import java.awt.AWTException; import java ...

  4. 窗口最小化消息的解决之道

    最近在弄程序的时候,碰到需要在主窗口最小化的时候,自动将其子窗口最小化的问题.当时没想通.不过现在明白了,其实就是在窗口大小变化的事件里判断主窗口是否最小化的.然后进行相应的操作即可.如果是在SDK程 ...

  5. 如何使对话框程序启动以及主窗口最小化时不在任务栏上显示

    时下流行的许多软件,如QQ,迅雷等,启动主程序以及主窗口最小化时,不在任务栏上显示按钮,这是怎么做到的呢? 首先说主窗口启动时不再任务栏上显示按钮的问题 方法1,将主窗口的属性设置为WS_EX_TOO ...

  6. qt 最小化到托盘linux,Qt窗口最小化到托盘,托盘菜单控制

    作为Qt初学者,最近在编写窗口最小化到托盘功能代码的时候遇到了点阻碍. Qt自带的demo实现的功能太过繁琐,涉及知识点又太杂,很难理出最核心的思路.网上的文章代码也很多脱骨于这个demo,注释说明太 ...

  7. MFC中将窗口最小化到系统托盘和还原

    通过以下步骤可以在MFC程序中将窗口最小化到系统托盘,和还原成窗口,附加代码中如有特殊说明则会用红色标出. 1.添加一个ICON图标,其ID为IDI_ICON_TESTICON,在VS2008坐标的R ...

  8. UG\NX二次开发 获取UG窗口句柄。实现操作UG窗口最小化、最大化、关闭功能

    文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: 获取UG窗口句柄.实现操作UG窗口最小化.最大化.关闭功能 代码: int doWo ...

  9. 窗口最小化后在任务栏上看不到

    本文出自Simmy的个人blog:西米在线  http://simmyonline.com/archives/645.html 症状:用户反应其程序点窗口最小化后,在任务栏上没有显示,如word, e ...

最新文章

  1. html编写app页面代码,编写html页面代码需要了解的--综合编
  2. php开源文件管理,搭建php开源的文件管理器eXtplorer
  3. hadoop学习记录
  4. 大数据工作流_大数据和人工智能时代下的数字化工作流
  5. vue打包代码反编译_Android逆向反编译代码注入APK过程思路分析
  6. 超级玛丽程序_如何构建一个超级快速的微笑跟踪应用程序
  7. (125)FPGA面试题-熟悉AXI总线吗,介绍AXI
  8. 高性能mysql 小查询_高性能MySQL06-查询优化(慢查询)
  9. centos6.5安装redmine2.6
  10. maven聚合工程打包_史诗级!有手就会的Maven教程(八)
  11. live2dmesh渲染优先级_如何渲染Live2D模型
  12. win7电脑网站服务器,Win7系统
  13. java 判断客户端是手机端还是PC端(SSH框架)
  14. 人工智能技术在电气自动化中的应用,主要有哪些?
  15. 【WiFi】WiFi6E 6G 信道与频宽对应关系
  16. Excel VBA基础教程
  17. Windows的SSH密钥获取
  18. 喜马拉雅产品分析报告
  19. 推荐使用什么样的平台表单制作工具好?
  20. Bootstrap 教程第四课:制作一组功能图标按钮

热门文章

  1. 中国越野车和皮卡市场趋势报告、技术动态创新及市场预测
  2. 图解 深入浅出JavaWeb:事务必会必知
  3. iterator的用法及概念
  4. MATLAB 画点图即连线
  5. 超过3万Mac已感染 “银麻雀”病毒 最新m1芯片也中招
  6. PHP初级学习(三)
  7. IOS APP 隐私政策
  8. 如何获取腾讯视频的MP4播放地址及mp4文件,无需进行qlv转换mp4格式【亲测效果】
  9. win10便签常驻桌面_盘点Win 10最好用的10个功能,排名第一的竟然是……
  10. perl linux 遍历文件,Perl/Linux过滤大文件与其他文件的内容