What you can learn by reading this blog

  • Create a 3D space
  • Effect of particle
  • Three.js handles the click event
  • Initial use of shaders
  • Achieve a halo effect

1. Create a 3D space

Can imagine we are in the room, the room is a cube, if you have a taste of life, may be in the room with wallpaper, three. Js can easily create a cube, and to its surrounding textures, let the camera in the cube, the camera can be rotated to 360, it simulates a real scenes.

Convert to code:

    const path = 'assets/image/'
    const format = '.jpg'
    const urls = [
      `${path}px${format}`, `${path}nx${format}`,
      `${path}py${format}`, `${path}ny${format}`,
      `${path}pz${format}`, `${path}nz${format}`
    ]
    const materials = []
    urls.forEach(url => {
      const textureLoader = new TextureLoader()
      textureLoader.setCrossOrigin(this.crossOrigin)
      const texture = textureLoader.load(url)
      materials.push(new MeshBasicMaterial({
        map: texture,
        overdraw: true,
        side: BackSide
      }))
    })
    const cube = new Mesh(new CubeGeometry(9000, 9000, 9000), new MeshFaceMaterial(materials))
    this.scene.add(cube)
Copy the code
  • CubeGeometry creates an oversized cube
  • The MeshFaceMaterial attaches a texture to the cube, since the perspective is inside the cube, so side: BackSide

2. Particle effects

A 3D model is composed of points, lines and planes. You can traverse every point of the model, convert each point into a geometric model, and attach a texture to it, copy the position of each point, and reconstruct a point-only model with these geometric models. This is the basic principle of particle effect.

this.points = new Group()
    const vertices = []
    let point
    const texture = new TextureLoader().load('assets/image/dot.png') geometry.vertices.forEach((o, => {// vertices. Push (o.lone ()) const _geometry = new Geometry() const pos = vertices. Push (o.lone ()) const pos = vertices. _geometry.vertices.push(new Vector3()) const color = new Color() color.r = Math.abs(Math.random() * 10) color.g = Math.abs(Math.random() * 10) color.b = Math.abs(Math.random() * 10) const material = new PointsMaterial({ color, size: Math.random() * 4 + 2, map: texture, blending: AddEquation, depthTest:false,
        transparent: true
      })
      point = new Points(_geometry, material)
      point.position.copy(pos)
      this.points.add(point)
    })
    return this.points
Copy the code
  • New Group creates a Group, so to speak, a set of particles
  • The particle and position are set by point-position.copy (pos). The coordinates are the same as the position of the corresponding point in the model

3. Click Event Handling

The click event of three.js requires the use of a Raycaster. To understand this, look at a diagram:

Raycaster emits a ray, and intersectObject monitors what the ray hits

This.raycaster = new Raycaster() // Store the array of seats you want to listen on this.seats. Push (seat) onTouchStart(event) {this.raycaster = new Seats () event.preventDefault() event.clientX = event.touches[0].clientX; event.clientY = event.touches[0].clientY; this.onClick(event) } onClick(event) { const mouse = new Vector2() mouse.x = ( event.clientX / this.renderer.domElement.clientWidth ) * 2 - 1 mouse.y = - ( event.clientY / this.renderer.domElement.clientHeight ) * 2 + 1; this.raycaster.setFromCamera(mouse, This. Camera) / / detection accuracy seat const intersects = this. Raycaster. IntersectObjects (enclosing seats)if (intersects.length > 0) {
        intersects[0].object.material = new MeshLambertMaterial({
            color: 0xff0000
        })
    }
  }
  
Copy the code
  • Length > 0 indicates that the ray hits a certain geometry
  • Lazy only implemented the mobile terminal click implementation, if you want to see how to achieve PC, please see the website of thee.js

4. Initial use of shaders

Shaders are divided into vertex shaders and chip shaders. They are written in GLSL language, which is a language to communicate with GPU


const vertext = `
   void main() {gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); } ` const fragment = ` uniform vec2 resolution; uniformfloat time;

    vec2 rand(vec2 pos)
    {
    returnFract (0.00005 * (pow(pos+2.0, pos. Yx + 1.0) * 22222.0)); } vec2 rand2(vec2 pos) {return rand(rand(pos));
    }

    float softnoise(vec2 pos, float scale)
    {
    vec2 smplpos = pos * scale;
    floatC0 = rand2(floor(smplpos) + Vec2 (0.0, 0.0))/scale).x; c0 = rand2(floor(smplpos) + Vec2 (0.0, 0.0))/scale).x;floatC1 = rand2(floor(smplpos) + VEC2 (1.0, 0.0))/scale).x; c1 = rand2(floor(smplpos) + Vec2 (1.0, 0.0))/scale).x;floatC2 = rand2(floor(smplpos) + Vec2 (0.0, 1.0))/scale).x;floatC3 = rand2((floor(smplpos) + VEC2 (1.0, 1.0))/scale).x; vec2 a = fract(smplpos);returnMix (mix (c0, c1, smoothstep (0.0, 1.0, a.x)), mix (c2 and c3, smoothstep (0.0, 1.0, a.x)), smoothstep (0.0, 1.0, a.y)); } void main(void) { vec2 pos = gl_FragCoord.xy / resolution.y; Pos.x += time * 0.1;floatColor = 0.0;floatS = 1.0;for(int i = 0; i < 8; I++) {color + = softnoise (pos + vec2 (I) * 0.02, s * 4.0)/s / 2.0; S * = 2.0; } gl_FragColor = vec4(color); } '// Set the object to a shaderlet material = new ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertext,
        fragmentShader: fragment,
        transparent: true,})Copy the code

5. Halo effect

Since it’s a simulated movie theater, I wanted to make a projector that simulates the light coming out of the projector.

// The halo effect must be set to alpha =true
 const renderer = this.renderer = new WebGLRenderer({alpha: true, antialias: true})

 let textureFlare = new TextureLoader().load('assets/image/lensflare0.png')
      let textureFlare3 = new TextureLoader().load('assets/image/lensflare3.png')
      let flareColor = new Color(0xffffff)
      letLensFlare = new lensFlare (textureFlare, 150, 0.0, AdditiveBlending, flareColor). Add (textureFlare3, 60, 0.6, AdditiveBlending); LensFlare. Add (textureFlare3, 70, 0.7, AdditiveBlending); LensFlare. Add (textureFlare3, 120, 0.9, AdditiveBlending); LensFlare. Add (textureFlare3, 70, 1.0, AdditiveBlending); lensFlare.position.set(0, 150, -85)Copy the code
  • The main light is still simulated by Lensflare0.png
  • TextureFlare3 Sets the range of the halo

Postscript:

Introductory tutorial

Original Blog address

Original is not easy, hard everyone big point a star

The source address