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着色器的原理实现的

 

posted @ 2024-08-24 17:13  火星写程序  阅读(54)  评论(0编辑  收藏  举报