引言
通过webgl的渲染方式,实现在二维地图上显示圆形扫描线,本文分享一下其中关键的shader代码。
vertex shader
代码如下:
//扫描线屏幕像素坐标
attribute vec4 a_position;
//屏幕分辨率
uniform vec2 u_resolution;
//中心点坐标
uniform vec2 u_center;
varying vec2 v_pos;
varying vec2 v_center;
void main() {
vec2 zeroToOne = a_position.xy / u_resolution;
vec2 clipSpace = (zeroToOne * 2.0 - 1.0)* vec2(1, -1);
gl_Position = vec4(clipSpace, 0, 1);
v_pos = a_position.xy;
v_center = u_center;
}
fragment shader
代码如下:
precision mediump float;
float M_PI=3.1415926535897932384626433832795;
//时间变化参数
uniform float u_time;
varying vec2 v_pos;
varying vec2 v_center;
float SMOOTH(float r, float R) {
return 1.0-smoothstep(R-1.0,R+1.0, r);
}
float movingLine(vec2 uv, vec2 center, float radius)
{
//根据时间变换线的角度
float theta0 = 90.0 * u_time;
vec2 d = uv - center;
float r = sqrt( dot( d, d ) );
if(r<radius)
{
vec2 p = radius*vec2(cos(theta0*M_PI/180.0),
-sin(theta0*M_PI/180.0));
float l = length( d - p*clamp( dot(d,p)/dot(p,p), 0.0, 1.0) );
d = normalize(d);
float theta = mod(180.0*atan(d.y,d.x)/M_PI+theta0,360.0);
float gradient = clamp(1.0-theta/45.0,0.0,1.0);
return SMOOTH(l,1.0)+0.5*gradient;
}
else return 0.0;
}
float circle(vec2 uv, vec2 center, float radius, float width)
{
float r = length(uv - center);
return SMOOTH(r-width/2.0,radius)-SMOOTH(r+width/2.0,radius);
}
void main() {
float _radius = distance(v_pos,v_center);
//半径根据外边的参数设定,这里默认写了200像素的半径
float deltinfo = movingLine(v_pos,v_center,200.0);
gl_FragColor = vec4(1.0, 0.0, 0.5, 0.75)*deltinfo+vec4(1.0, 0.0, 0.1, 0.75)*circle(v_pos,v_center,198.0,2.0);
}
效果如下: