今天我们一起来做一个三原色的旋转,为了更好的体现效果呢,我没有使用图片作为背景,闲言少叙,我们直接看效果。
图中就是我们要实现的效果,有红蓝绿三种颜色的圆圈在旋转,我们需要解决的主要问题有如何使用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