ThreeJS Shader的效果样例雷达图和大气层(二)
一、雷达图
实现原理:图中是一个旋转的渐变扇形,可以通过先实现一个扇形、然后再实现一个渐变扇形,最后再将扇形旋转来达到最终效果
1. 实现一个夹角为O的扇形,已X轴正方向为单位向量M,UV点到(0,0)形成向量N,通过M和N的点乘就可以得到一个夹角,然后判断角度小于O就可以了
2. 实现扇形的渐变色,主要是通过smoothstep实现,smoothstep是在两个值之间取渐变值,这样就可以实现离X轴越远越暗的效果
3. 如何让扇形旋转起来呢,上面已经实现了一个扇形A,通过将扇形B按照一定角度旋转到A,就可以得到对应的渐变色颜色值了,这样一个渐变的旋转角度就可以实现一个旋转的渐变扇形
4. 实现蓝色线圈,也是通过smoothstep函数,一个smoothstep最后会生成0-1的跳变值,如果是两个smoothstep相减会生成一个波峰的颜色值
主要原理是先实现一个扇形渐变的区域,这个不是很复杂,然后通过不断渲染页面时,将该扇形旋转到某个角度即可
const vertex = '\ varying vec2 vUv;\ void main() {\ vUv = uv;\ vec4 modelPosition = modelMatrix * vec4(position, 1.0);\ gl_Position = projectionMatrix * viewMatrix * modelPosition;\ }\ '; const frag = '\ uniform float uTime;\ varying vec2 vUv;\ float drawCircle(vec2 vUv, float radius) {\ float res = length(vUv);\ float width = 0.005;\ return smoothstep(radius - width, radius, res) - smoothstep(radius, radius + width, res);\ }\ float drawSector(vec2 vUv, float radius) {\ float angle = uTime;\ vec2 newvUv = mat2(cos(angle), sin(angle), -sin(angle), cos(angle)) * vUv;\ vec2 x = vec2(1.0, 0.0);\ vec2 y = vec2(0.0, 1.0);\ float res = dot(newvUv, y);\ float angle2 = acos(dot(x, normalize(newvUv)));\ if (angle2 > 0.0 && angle2 < 1.5707 && length(newvUv) < 0.45 && res > 0.0) {\ return 1.0 - smoothstep(0.0, 1.5707, angle2);\ } else {\ return 0.0;\ }\ }\ void main() {\ vec2 newvUv = vUv;\ newvUv -= vec2(0.5);\ vec3 color = vec3(0.0, 0.0, 0.0);\ float circle = drawCircle(newvUv, 0.45);\ float circle2 = drawCircle(newvUv, 0.3);\ float circle3 = drawCircle(newvUv, 0.1);\ color += circle + circle2 + circle3;\ color += drawSector(newvUv, 0.45);\ gl_FragColor = vec4(color * vec3(0.0, 1.0, 0.0), 1.0);\ }\ ';
三、遮罩层
1. 第一种方法:采用shader中法向量的概念,取法向量和球体上各个坐标点与相机形成的向量之间的点积,离相机位置越近,
越靠近相机位置,点积值越大,且为正值,反之越远,则点积越小,同时可能为负值,这时候用产生的点积数据作为透明度,
即可得到渐变的效果
var vertex = 'varying vec3 vVertexWorldPosition;\ varying vec3 vVertexNormal;\ varying vec4 vFragColor;\ void main(){\ vVertexNormal = normalize(normalMatrix * normal);\ vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\ }'; var frag = 'uniform vec3 glowColor;\ uniform float coeficient;\ varying vec3 vVertexNormal;\ varying vec3 vVertexWorldPosition;\ varying vec4 vFragColor;\ void main(){\ vec3 worldVertexToCamera = cameraPosition - vVertexWorldPosition;\ vec3 viewCameraToVertex = (viewMatrix * vec4(worldVertexToCamera, 0.0)).xyz;\ viewCameraToVertex = normalize(viewCameraToVertex);\ float intensity = coeficient + dot(vVertexNormal, viewCameraToVertex);\ if (intensity < 0.0) {\ gl_FragColor = vec4(vec3(0.0, 1.0, 0.0), 1.0);\ } else {\ gl_FragColor = vec4(glowColor, intensity);\ }\ }';
2. 第二种方法通过ThreeJS官方提供的样例,使用EffectCompose的方式来实现,其中也是通过添加shader着色器的原理实现的