博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
webgl滤镜--旋转的三原色
阅读量:7153 次
发布时间:2019-06-29

本文共 3385 字,大约阅读时间需要 11 分钟。

今天我们一起来做一个三原色的旋转,为了更好的体现效果呢,我没有使用图片作为背景,闲言少叙,我们直接看效果。

图中就是我们要实现的效果,有红蓝绿三种颜色的圆圈在旋转,我们需要解决的主要问题有如何使用webgl来画一个模糊的圆圈,如何使三个圆圈绕一点旋转。

同时如果你喜欢的话还可以自己做一个延伸,例如时刻更改旋转的中心等等,这样效果会更佳的丰富,我在这里呢就不做延伸了。

基础的构建我在这里就不在赘述了,你可以看一下我的另一篇基础构建的文章,在此我们直接进入最核心的webgl的片元着色器代码。

一 webgl画出一个圆圈

precision mediump float;varying vec2 uv;uniform float time;void main(){	vec3 color;	float blur = 15.0;		color.b =  1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;	gl_FragColor = vec4(color, 1.0 );}复制代码

我们使用上面的代码就轻松的构建出了一个圆,接下来我们就看一下这个轻松画出圆的原理。

首先我们定义了一个vec3类型的变量,这个变量的作用就是用来存储我们改变以后的色值的。
接着我们定义了一个float类型的blur变量,此变量的作用是用来控制画出圆的模糊距离。

color.b =  1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;复制代码

这句代码是画出圆的关键点,我们使用具体的坐标事例来说明。

图中的坐标系中我们定义了我们想要画圆的点A(0.5,0.8),其坐标你可以在上面的公式找到。

我们分别将W,X,U点带入公式看一下。
pow函数是平方函数,pow(x,y)会返回x的y次方。

W => 1.0-(pow(0.5 - 0.5, 2.0) + pow(0.77 - 0.8, 2.0))*15.0 => 0.865

X => 1.0-(pow(0.5 - 0.5, 2.0) + pow(0.4 - 0.8, 2.0))*15.0 => -1.4 U => 1.0-(pow(0.1 - 0.5, 2.0) + pow(0.1 - 0.8, 2.0))*15.0 => -8.75

我们在整个二维平面上面,距离A点越远的点最后计算出来的值就越大。

在webgl中rgba的取值范围是在0.0~1.0。

也就是说从A点为圆心,距离A越远的点计算出来的值会越小,也就会呈现黑色,距离A点越近的点就会月靠近1.0这个数值,也就会呈现蓝色。

二 画出三色圆

一个圆的画法我们已经知道了,那么我们画出来三个圆。

precision mediump float;varying vec2 uv;uniform float time;void main(){	vec3 color;	float blur = 15.0;		color.r =  1.0 - (pow(uv.x - 0.24,2.0) + pow(uv.y - 0.35,2.0))*blur;	color.g =  1.0 - (pow(uv.x - 0.75,2.0) + pow(uv.y - 0.35,2.0))*blur;	color.b =  1.0 - (pow(uv.x - 0.5,2.0) + pow(uv.y - 0.8,2.0))*blur;	gl_FragColor = vec4(color, 1.0 );}复制代码

上面我们使用和画蓝色圆同样的方式画出了三色圆,那么接下来就是让三色圆进行转动了。

三 转动三色圆

precision mediump float;varying vec2 uv;uniform float time;void main(){	vec3 color;	float blur = 15.0;	vec2 rotateCenter = vec2(0.5, 0.5);	vec2 circleA = vec2(rotateCenter.x + 0.3*cos(radians(90.0+time)), rotateCenter.y + 0.3*sin(radians(90.0+time)));	vec2 circleB = vec2(rotateCenter.x + 0.3*cos(radians(210.0+time)), rotateCenter.y + 0.3*sin(radians(210.0+time)));	vec2 circleC = vec2(rotateCenter.x + 0.3*cos(radians(-30.0+time)), rotateCenter.y + 0.3*sin(radians(-30.0+time)));	color.r =  1.0 - (pow(uv.x - circleB.x,2.0) + pow(uv.y - circleB.y,2.0))*blur;	color.g =  1.0 - (pow(uv.x - circleC.x,2.0) + pow(uv.y - circleC.y,2.0))*blur;	color.b =  1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.y,2.0))*blur;	gl_FragColor = vec4(color, 1.0 );}复制代码

我们首先定义三色圆的旋转中心,我定义的是rotateCenter(0.5,0.5),接下来我们要将三色圆的圆心和这个点关联起来。

上面图中A点是蓝色圆的圆心,B点是红色圆的圆心,C点是绿色圆的圆心,O点是圆的圆心,同时也是三角形的中心。
我们可以根据初高中的知识知道: A(x1,y1),o(x0,y0)
x1 = x0 + r*cos(degrees*PI/180)
y1 = y0 + r*sin(degrees*PI/180)

vec2(rotateCenter.x + 0.3*cos(radians(90.0)), rotateCenter.y + 0.3*sin(radians(90.0)))复制代码

在代码中rotateCenter.x就是x0

rotateCenter.y就是y0
0.3就是r也就是圆的半径
degrees*PI/180我们使用webgl的内置三角函数radians(90.0)进行计算,其中90.0就是A点相对于O点的角度。
这样我们就将ABC三个点和O点关联上了,此时只要我们再时时的改变ABC三点相对于O点的角度值,这样就可以达到旋转的效果了。

vec2 circleA = vec2(rotateCenter.x + 0.3*cos(radians(90.0+time)), rotateCenter.y + 0.3*sin(radians(90.0+time)));复制代码

在上面我们在radians(90.0+time)的参数中添加了一个变量time,这个time会从0开始一直加1,这样ABC三个点就会时时的改变相对于O点的角度,进而完成旋转。

color.b =  1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.y,2.0))*blur;复制代码

最后我们将时时旋转的三色圆中心坐标传给颜色画圆的计算公式,这样就完成了。

旋转的方式你可以自己手动的更改,并且画圆那里使用2次方还是1次方你都可以进行更改,你会得到不一样的效果,篇幅的原因我就不一个个举例子了。

color.b =  1.0 - (pow(uv.x - circleA.x,2.0) + pow(uv.y - circleA.x,2.0))*blur;复制代码

嗯,怕你感觉对实现的效果失望,你只需要将color.b那里的旋转中新都设置成x就会出现上面的效果,更多的效果你可以自己尝试一下。

最后附上代码地址:

此次的代码是项目下面的rotateRGB.html

转载地址:http://oulgl.baihongyu.com/

你可能感兴趣的文章
触碰jQuery:AJAX异步详解
查看>>
【leetcode】1053. Previous Permutation With One Swap
查看>>
linux复制文件夹到另一个文件夹并排除一个文件夹
查看>>
sqlite基础API
查看>>
jsp-九大内置对象
查看>>
文本占用的高度和范围
查看>>
【BZOJ】2038: [2009国家集训队]小Z的袜子(hose)
查看>>
6月14日奋战es5基础-1
查看>>
Socket IO与NIO(六)
查看>>
一图胜千言,8张图理解Java
查看>>
[算法]动态规划之最长递增子序列
查看>>
好程序员告诉你Java架构师学习路线
查看>>
Redis之主从集群环境搭建
查看>>
tab切换小例子
查看>>
Java封装
查看>>
【快学springboot】9.使用 @Transactional 注解配置事务管理
查看>>
匿名对象方案与实体对象方案对比
查看>>
NTP服务放大攻击的解决办法
查看>>
SQL SERVER 占用资源高的SQL语句
查看>>
lombok 安装
查看>>